C# の隠し機能に関する投稿を見ましたが、多くの人が linq/lambdas の例を書いているわけではないので...
これまでに見た/書いた C# LINQ および/またはラムダ/匿名デリゲートの最もクールな (最もエレガントな) 使用法は何ですか?
それも生産に入った場合のボーナス!
C# の隠し機能に関する投稿を見ましたが、多くの人が linq/lambdas の例を書いているわけではないので...
これまでに見た/書いた C# LINQ および/またはラムダ/匿名デリゲートの最もクールな (最もエレガントな) 使用法は何ですか?
それも生産に入った場合のボーナス!
LINQ Raytracerは確かに私のリストのトップです =)
エレガントと言えるかどうかは定かではありませんが、私が今まで見た中で最もクールな linq-expression であることは間違いありません!
ああ、非常に明確にするために。私が書いたのではありません(ルーク・ホーバンが書きました)
いくつかの基本的な機能:
public static class Functionals
{
// One-argument Y-Combinator.
public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F)
{
return t => F(Y(F))(t);
}
// Two-argument Y-Combinator.
public static Func<T1, T2, TResult> Y<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> F)
{
return (t1, t2) => F(Y(F))(t1, t2);
}
// Three-arugument Y-Combinator.
public static Func<T1, T2, T3, TResult> Y<T1, T2, T3, TResult>(Func<Func<T1, T2, T3, TResult>, Func<T1, T2, T3, TResult>> F)
{
return (t1, t2, t3) => F(Y(F))(t1, t2, t3);
}
// Four-arugument Y-Combinator.
public static Func<T1, T2, T3, T4, TResult> Y<T1, T2, T3, T4, TResult>(Func<Func<T1, T2, T3, T4, TResult>, Func<T1, T2, T3, T4, TResult>> F)
{
return (t1, t2, t3, t4) => F(Y(F))(t1, t2, t3, t4);
}
// Curry first argument
public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> F)
{
return t1 => t2 => F(t1, t2);
}
// Curry second argument.
public static Func<T2, Func<T1, TResult>> Curry2nd<T1, T2, TResult>(Func<T1, T2, TResult> F)
{
return t2 => t1 => F(t1, t2);
}
// Uncurry first argument.
public static Func<T1, T2, TResult> Uncurry<T1, T2, TResult>(Func<T1, Func<T2, TResult>> F)
{
return (t1, t2) => F(t1)(t2);
}
// Uncurry second argument.
public static Func<T1, T2, TResult> Uncurry2nd<T1, T2, TResult>(Func<T2, Func<T1, TResult>> F)
{
return (t1, t2) => F(t2)(t1);
}
}
それらの使い方を知らなければ、何の役にも立ちません。それを知るためには、それらが何のためにあるのかを知る必要があります:
私が今まで出会った中で最も印象的な Linq 実装は、Brahma フレームワークです。
「Linq to GPU」を使用して並列計算を GPU にオフロードするために使用できます。linq で「クエリ」を記述し、Brahma がそれを HLSL (High Level Shader Language) に変換して、DirectX が GPU で処理できるようにします。
このサイトではリンクを 1 つしか貼り付けられないので、dotnetrocks からの次の Web キャストを試してください。
http://www.dotnetrocks.com/default.aspx?showNum=466
それ以外の場合は、Brahma Project を Google で検索すると、適切なページが表示されます。
非常にクールなもの。
GJ
Progress Reporting for long running LINQ queries. In the blog post you can find an extension method WithProgressReporting() that lets you discover and report the progress of a linq query as it executes.
私にとって、デリゲート ( Func<T,R>
, Action<T>
) と式 ( Expression<Func<T,R>>
Expression<Action<T>>
) の間の二重性は、ラムダの最も賢い使い方を生み出すものです。
例えば:
public static class PropertyChangedExtensions
{
public static void Raise(this PropertyChangedEventHandler handler, Expression<Func<object>> propertyExpression)
{
if (handler != null)
{
// Retrieve lambda body
var body = propertyExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("'propertyExpression' should be a member expression");
// Extract the right part (after "=>")
var vmExpression = body.Expression as ConstantExpression;
if (vmExpression == null)
throw new ArgumentException("'propertyExpression' body should be a constant expression");
// Create a reference to the calling object to pass it as the sender
LambdaExpression vmlambda = Expression.Lambda(vmExpression);
Delegate vmFunc = vmlambda.Compile();
object vm = vmFunc.DynamicInvoke();
// Extract the name of the property to raise a change on
string propertyName = body.Member.Name;
var e = new PropertyChangedEventArgs(propertyName);
handler(vm, e);
}
}
}
INotifyPropertyChanged
次に、呼び出すことで「安全に」実装できます
if (PropertyChanged != null)
PropertyChanged.Raise( () => MyProperty );
注 : 最初は数週間前にウェブで見たのですが、その後リンクを失い、それ以来、さまざまなバリエーションがあちこちで発生しているため、適切な帰属を示すことができません。
実際、私は Excel ドキュメントを生成できることを非常に誇りに思っています: http://www.aaron-powell.com/linq-to-xml-to-excel
Not my design but I've used it a few times, a typed-switch statement: http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx
Saved me so many if... else if... else if... else IF! statements
私は最近、そのようなことを1つ(少しクレイジーですが、興味深い)行いました:
LINQ は .NET に対する大きな変更点であり、非常に強力なツールだと思います。
本番環境で LINQ to XML を使用して、2 行のコードで 6 MB の XML ファイル (ノード レベルが 20 以上) のレコードを解析し、データセットにフィルター処理します。
LINQ が導入される前は、数百行のコードとデバッグに何日もかかっていました。
それが私がエレガントと呼ぶものです!
おそらく最もクールではありませんが、最近、C + Pdを何度も何度も取得して数行を変更するだけのコードブロックがあるときはいつでもそれらを使用しています。たとえば、単純な SQL コマンドを実行してデータを取得するには、次のようにします。
SqlDevice device = GetDevice();
return device.GetMultiple<Post>(
"GetPosts",
(s) => {
s.Parameters.AddWithValue("@CreatedOn", DateTime.Today);
return true;
},
(r, p) => {
p.Title = r.Get<string>("Title");
// Fill out post object
return true;
}
);
今日作成された投稿のリストを返すことができます。このようにして、コマンド、オブジェクトなどごとに try-catch-finally ブロックを 1,500 万回コピー アンド ペーストする必要がなくなります。
私が構築している Web サイトのナビゲーション コントロールを構築するためのクールな方法を考え出そうとしていました。通常の HTML 順序なしリスト要素 (標準的なCSS の「吸盤魚」の外観を採用) を使用して、ドロップダウン項目を表示するトップ ナビゲーションのマウス オーバー効果を使用したいと考えていました。2 つのテーブル (NavigationTopLevels と NavigationBottomLevels) を持つ SQL 依存のキャッシュされた DataSet がありました。次に、2 つのクラス オブジェクト (TopNav と SubNav) をいくつかの必須プロパティと共に作成するだけで済みました (TopNav クラスには、bottomnav アイテムの汎用リストが必要でした -> List<SubNav> SubItems)。
var TopNavs = ds.NavigationTopLevels の n から 新しいトップナビを選択 { NavigateUrl = String.Format("{0}/{1}", tmpURL, n.id), テキスト = n.テキスト、 id = n.id、 SubItems = new List<SubNav>( ds.NavigationBottomLevels の si から どこで si.parentID == n.id 新しいサブナビを選択 { id = si.id、 レベル = si.NavLevel, NavigateUrl = String.Format("{0}/{1}/{2}", tmpURL, n.id, si.id), 親 ID = si.親 ID、 Text = si.Text } ) }; List<TopNav> TopNavigation = TopNavs.ToList();
これは「最もクール」ではないかもしれませんが、動的なナビゲーションが必要な多くの人にとって、それに付随する通常のループ ロジックをいじる必要がないのは素晴らしいことです。この場合、LINQ は時間の節約になります。
INotifyingCollection に対する OLINQ リアクティブ LINQ クエリ - これらを使用すると、(とりわけ) 大規模なデータセットに対してリアルタイムの集計を実行できます。
属性の操作:
private void WriteMemberDescriptions(Type type)
{
var descriptions =
from member in type.GetMembers()
let attributes = member.GetAttributes<DescriptionAttribute>(true)
let attribute = attributes.FirstOrDefault()
where attribute != null
select new
{
Member = member.Name,
Text = attribute.Description
};
foreach(var description in descriptions)
{
Console.WriteLine("{0}: {1}", description.Member, description.Text);
}
}
GetAttributes
拡張方法:
public static class AttributeSelection
{
public static IEnumerable<T> GetAttributes<T>(this ICustomAttributeProvider provider, bool inherit) where T : Attribute
{
if(provider == null)
{
throw new ArgumentNullException("provider");
}
return provider.GetCustomAttributes(typeof(T), inherit).Cast<T>();
}
}
AttributeSelection
は製品コードであり、 および も定義GetAttribute
してHasAttribute
います。let
この例ではandwhere
節を使用することにしました。