C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: 違いはなんなのでしょうか?


(過去ログ 140 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■82082 / inTopicNo.1)  違いはなんなのでしょうか?
  
□投稿者/ 夜叉丸 (27回)-(2016/12/08(Thu) 17:41:11)

分類:[.NET 全般] 

以下の2つの書き方は表記が違うだけ内部の処理的には同様なのでしょうか?
つまり、同じように表記したものは速度的にはどちらも同じだとか、

ちなみに、下側は .OrderBy(r => r.CODE, r.TNO)
という表記ができなかったので、変更しています。

var vartjname = (from r in dt
orderby r.CODE, r.TNO
select r.NAME).Distinct().ToArray();

var vartjname2 = dt
.OrderBy(r => r.CODE)
.Select(r => r.NAME).Distinct().ToArray();



合わせて下側の OrderBy で複数指定する方法も教えてください

引用返信 編集キー/
■82083 / inTopicNo.2)  Re[1]: 違いはなんなのでしょうか?
□投稿者/ Hongliang (474回)-(2016/12/08(Thu) 17:47:33)
2016/12/08(Thu) 17:47:58 編集(投稿者)
コンパイル結果は同じになります。

var vartjname2 = dt
	.OrderBy(r => r.CODE)
	.ThenBy(r => r.NAME)
	.Select(r => r.NAME).Distinct().ToArray();

引用返信 編集キー/
■82086 / inTopicNo.3)  Re[2]: 違いはなんなのでしょうか?
□投稿者/ 夜叉丸 (28回)-(2016/12/08(Thu) 18:23:39)
No82083 (Hongliang さん) に返信

ありがとうございます。

結果も速度も変わらないのであれば
好き好きでどちらでもよいということですね?

2種類あるのはメリット、デメリットがあるってことですよね
orderby は複数選択できるが、
.OrderBy は複数選べないとか

引用返信 編集キー/
■82087 / inTopicNo.4)  Re[1]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (999回)-(2016/12/08(Thu) 18:36:59)
No82082 (夜叉丸 さん) に返信
> ちなみに、下側は .OrderBy(r => r.CODE, r.TNO)
> という表記ができなかったので、変更しています。

であれば、前者も orderby r.CODE, r.TNO ではなく orderby r.CODE に
しておかないと比較にならない気が。(^^;


> 以下の2つの書き方は表記が違うだけ内部の処理的には同様なのでしょうか?

その 2 つでいうと、内部的には後者の方が単純化されます。
r.TNO での並び替えがありませんからね。


> var vartjname = (from r in dt
> orderby r.CODE, r.TNO
> select r.NAME).Distinct().ToArray();

こちらは、
 var vartjname = dt
 .OrderBy(r => r.CODE).ThenBy(r => r.TNO)
 .Select(r => r.NAME).Distinct().ToArray();

の意味になります。ThenBy の分だけ、

> var vartjname2 = dt
> .OrderBy(r => r.CODE)
> .Select(r => r.NAME).Distinct().ToArray();

よりも処理が増えることになりますね。



> つまり、同じように表記したものは速度的にはどちらも同じだとか、
同じです。ただし、メソッド構文でなければ記述できない処理もあります。


> 合わせて下側の OrderBy で複数指定する方法も教えてください
上記コード例を参照。


ちなみに VB の場合は、クエリ構文にも Distinct があります。

Dim vartjname = (
From r In dt
Order By r.CODE, r.NAME
Select r.NAME Distinct
).ToArray()

引用返信 編集キー/
■82088 / inTopicNo.5)  Re[2]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (1000回)-(2016/12/08(Thu) 18:50:55)
No82087 (魔界の仮面弁士) に追記
> VB の場合
> Dim vartjname = (
> From r In dt
> Order By r.CODE, r.NAME
> Select r.NAME Distinct
> ).ToArray()

「Order By r.CODE, r.TNO」の間違いです。



No82086 (夜叉丸 さん) に返信
> 2種類あるのはメリット、デメリットがあるってことですよね

クエリ構文の方が短く書ける場合は、それがメリットと言えるかも知れません(let を使う場合とか)。
メソッド構文の方が汎用性は高いです。クエリ構文はメソッド構文の糖衣構文(シンタックスシュガー)です。
メソッド構文でなければ書けない処理もありますが、その逆は無いはずですし、
メソッド構文なら独自の拡張メソッドを使うということもできるわけなので、
個人的にはメソッド構文をおすすめしています。C# の場合は。

これが VB だと、微妙なところなんですけれども。(VB のラムダ式は記述が冗長的なので)


> orderby は複数選択できるが、
> .OrderBy は複数選べないとか
ThenBy を知らなかったとしても、複数項目での並び替えは可能ですよ。

.OrderBy(r => r.TNO).OrderBy(r => r.CODE)

とすれば、orderby r.CODE, r.TNO 相当になりますので。
引用返信 編集キー/
■82089 / inTopicNo.6)  Re[3]: 違いはなんなのでしょうか?
□投稿者/ 夜叉丸 (29回)-(2016/12/09(Fri) 08:50:52)
2016/12/09(Fri) 10:20:29 編集(投稿者)

データベースのセレクトメソッドは遅いのでLINQを使ったほうがよいとあったので。
LINQを使った方がいいと思っているのですが、

メソッド構文 dt.Select()
クエリ構文 from r in dt select
速度の違いはないんですか?

私は何か勘違いしているのでしょうか?


引用返信 編集キー/
■82090 / inTopicNo.7)  Re[4]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (1001回)-(2016/12/09(Fri) 09:35:51)
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# においては)。
もちろん機能的に不足が無い場合は、クエリ構文でも問題ないでしょう。
引用返信 編集キー/
■82091 / inTopicNo.8)  Re[5]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (1002回)-(2016/12/09(Fri) 09:58:30)
No82090 (魔界の仮面弁士 さん) に補足
> どちらの構文で記述したとしても、コンパイル結果は等しく、
>  var q = System.Linq.Enumerable.Select(dt, selector);
> というメソッド呼び出しに置き換えられるためです。Where 等も同様。

それと LINQ には幾つかの種類があり、すべての select クエリや .Select 拡張メソッドが
System.Linq.Enumerable クラスの Select<TSource, TResult> メソッドになるわけではありません。

たとえば DataContext のテーブル System.Data.Linq.Table<TEntity> に対する
select クエリや .Select 拡張メソッドの場合は、System.Linq.Queryable クラスの
.Select<TSource, TResult> メソッドの呼び出しとなります。
この場合の戻り値は、IEnumerable<> ではなく IQueryable<T> です。


結局の所、いずれも『糖衣構文(シンタックスシュガー)』に過ぎません。
たとえば、

public static class Sample
{
  public static double Select(this int x, Func<int, double> selector)
  {
    return selector(x);
  }
}

という拡張メソッドを用意しておけば、

var q1 = from r in 123 select (double)r;
var q2 = 123.Select(r => (double)r);

という LINQ 構文が使えるようになったりします。
※上記の結果は、いずれも double 型の 123.0 を返します。
引用返信 編集キー/
■82092 / inTopicNo.9)  Re[6]: 違いはなんなのでしょうか?
□投稿者/ 夜叉丸 (30回)-(2016/12/09(Fri) 10:27:45)
No82091 (魔界の仮面弁士 さん) に返信


dt.SELECT("CODE=" + code.ToString());
このようなSelect構文も同様に速度は変わらないのでしょうか?

引用返信 編集キー/
■82093 / inTopicNo.10)  Re[7]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (1003回)-(2016/12/09(Fri) 10:35:08)
No82092 (夜叉丸 さん) に返信
> dt.SELECT("CODE=" + code.ToString());
> このようなSelect構文も同様に速度は変わらないのでしょうか?

何と何の速度でしょうか?


まず、『"CODE=" + code.ToString()』はラムダ式ではありませんので、

 string arg = "CODE=" + code.ToString();
 dt.SELECT(arg);

と同義になります。

次に、そもそも dt.SELECT は、dt.Select とは異なり
「拡張メソッド」ですらありません。


SELECT (≠Select)という名のメソッドか拡張メソッドが用意されていれば
呼べますが、いずれにしても対応するクエリ構文は存在しませんので、
何と何の速度差を比較しようとしているのか、質問の意図が読み取れませんでした。
引用返信 編集キー/
■82095 / inTopicNo.11)  Re[7]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (1004回)-(2016/12/09(Fri) 13:54:22)
No82092 (夜叉丸 さん) に返信
> dt.SELECT("CODE=" + code.ToString());
> このようなSelect構文も同様に速度は変わらないのでしょうか?

もしかして、System.Data.DataTable クラスが持つ、
拡張メソッドでは無いほうの Select (≠SELECT) メソッドのことでしょうか。

だとしたら、指定した文字列式はコンパイル時解釈ではなく、
実行時解釈となるため、LINQ に比べると比較的低速です。
(それを抜きにしても、そもそも DataTable 自体が比較的重いのですが)


そう言えば、当初の質問( No82082 )のクエリ式は、型付 DataSet 上の
DataTable (正確には System.Data.TypedTableBase<T> )にも見えますね…。
引用返信 編集キー/
■82096 / inTopicNo.12)  Re[8]: 違いはなんなのでしょうか?
□投稿者/ 魔界の仮面弁士 (1005回)-(2016/12/09(Fri) 14:20:08)
No82089 (夜叉丸 さん) に返信
> データベースのセレクトメソッドは遅いので

『データベースのセレクトメソッド』というのが
何を指しているのか曖昧なので回答し難いのですが:

LINQ to Entities の話なら、No82091 を参照してください。

LINQ to Object の話なら、No82090 の回答を参照してください。

LINQ to DataSet の話だとしたら、.Select 拡張メソッドや select クエリ構文は、
System.Data.EnumerableRowCollectionExtensions クラスの
Select<TRow, S> メソッドへと展開されてコンパイルされることになります。

※型付(DataTable の派生クラスとなる System.Data.TypedTableBase<T>)の場合、
 直接 dt.Select(…) などとして拡張メソッドを呼べますが、素の DataTable の場合は、
 dt.AsEnumerable().Select(…) などと書く必要があります。


どの LINQ を使うにしても、「クエリ構文」と「メソッド構文」とで
動作に変わりはありません。いずれも拡張メソッドの呼び出しを意味します。



No82095 (魔界の仮面弁士) に追記
> そう言えば、当初の質問( No82082 )のクエリ式は、型付 DataSet 上の
> DataTable (正確には System.Data.TypedTableBase<T> )にも見えますね…。

No82089 の『データベースのセレクトメソッド』や
No82092 の『dt.SELECT("CODE=" + code.ToString());』というのが、
拡張メソッドの Select のことではなく、
No82095 にて推察した DataTable.Select メソッドのことだとしたら、
そもそも LINQ の select と比較するのが不自然な話です。機能的には
select ではなく、where(あるいは where + orderby)に相当するからです。

これがパフォーマンス面で劣るというのは、No82095 で述べた通り。



それとも『データベースのセレクトメソッド』というのは、
SQL Server や Oracle 等に対して
SELECT クエリーを発行する場合との比較なのでしょうか。

だとしたらそれは、元のデータ量や抽出条件に依存する話なので、
LINQ かどうかとは直接関係無いと思います。ケースバイケースでしょう。


たとえば、検索頻度が多い割に更新頻度の低い情報の場合、
「毎回サーバーに問い合わせる」よりも、ローカルにキャッシュしておいた
DataTable 等から Select メソッドでローカルキャッシュから問い合わせたり、
LINQ で取得したり、Dictionary.TryGetValue で取り出すなどした方が
早いことはありえます。データの内容によっては遅くもなりえますが。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -