|
2016/12/09(Fri) 10:13:12 編集(投稿者)
■No82089 (夜叉丸 さん) に返信 > メソッド構文 dt.Select() > クエリ構文 from r in dt select > 速度の違いはないんですか?
速度は変わりません。
どちらの構文で記述したとしても、コンパイル結果は等しく、 var q = System.Linq.Enumerable.Select(dt, selector); というメソッド呼び出しに置き換えられるためです。Where 等も同様。
また、Enumerable.Select を直接呼び出す方法を取れば、たとえ LINQ がまだ導入されていなかった頃の Visual C# 2005 であっても IEnumerable<TR> q = System.Linq.Enumerable.Select<TS, TR>(dt, selector); という記述で LINQ を利用することができます。 この場合、.NET 3.5 の System.Core.dll を参照設定する必要がありますけれどね。 (.NET 3.5 は CLR2 ベースなので、2005 からも一応呼び出せます)
C# 2.0 当時はラムダ式がありませんが、匿名メソッドは使えますので、 Enumerable.Select(dt, item => item.X); // dt が Cls[]、item.X が int の場合 というコードを Enumerable.Select<Cls, int>(dt, delegate(C item) { return item.X; }); へと記述することができます。型推論が無いので var で受け取れませんし、 匿名型も無いので、C# 3.0 (Visual C# 2008)と比べると冗長的ではありますが。
そして C# 3.0 では拡張メソッドが追加されました。 Enumerable.Select は IEnumerable<> への拡張メソッドなので、 System.Linq 名前空間を using してさえいれば、 var q = dt.Select(selector); という糖衣構文で書くこともできるようになりました。 コンパイル結果は同じなので、どちらで書いても速度面で差はありません。 (ご存知かと思いますが、ToArray も拡張メソッドです)
そしてそれをさらに SQL ライクの糖衣構文にしたものが いわゆるクエリ構文と言うことです。これもコンパイル結果は変わりません。 (ToArray にはクエリ構文が無いですね)
ついでに言えば、 Enumerable.Select には 2 つのオーバーロードが存在します。 第二引数が "Func<TSource, TResult> selector" であるものと 第二引数が "Func<TSource, int, TResult> selector" であるものです。
このうち、クエリ構文で呼び出せるのは、Func<TSource, TResult> のみです。 Func<TSource, int, TResult> を使うと、int な引数によって、 「何番目に列挙された要素なのか」を得られるのですが、これを呼び出すためには メソッド構文を使う(または Enumerable.Select を直接呼び出す)しかなく、 クエリ構文では対処できません。
なので個人的には、メソッド構文の方をお奨めしています(特に C# においては)。 もちろん機能的に不足が無い場合は、クエリ構文でも問題ないでしょう。
|