LINQの最も難しい、または最も誤解されている側面は何ですか?[閉まっている]


282

背景:来月は、について、または少なくともLINQに関連して3つの講演を行いますC#。人々が理解するのが難しいと思うことや、彼らが誤った印象を持っているかもしれないことに基づいて、かなりの注意を払う価値のあるトピックを知りたいのです。私は特にについて話されることはありませんLINQへのSQLクエリが式ツリー(通常は使用してリモートで実行することができる方法の例として以外またはEntity FrameworkのIQueryable)を。

それで、あなたは何が難しいと思いましたLINQか?誤解に関してあなたは何を見ましたか?例は次のいずれかですが、自分を制限しないでください!

  • どのようにC#コンパイラの扱いクエリ表現
  • ラムダ式
  • 式の木
  • 拡張メソッド
  • 匿名型
  • IQueryable
  • 遅延実行と即時実行
  • ストリーミングとバッファリングされた実行(たとえば、OrderByは据え置かれますが、バッファリングされます)
  • 暗黙的に型付けされたローカル変数
  • 複雑な一般的な署名の読み取り(例:Enumerable.Join

3
あなたがこれらの講演をいつ行うのか、そしてオンラインでそれらを表示する方法があるかどうかを知りたいと思います
Mark Heath

2
最初の話:コペンハーゲン、10月30日。うまくいけば、これは録音されるでしょう。(終日!)2番目の講演:ロンドン、11月19日夜、ロンドン.NETユーザーグループ、おそらくプッシュLINQ。3番目の講演:11月22日の読書、開発者開発者の日、LINQ to Objectsを60分で実装。
Jon Skeet、

1
反対投票者:説明コメントを追加してください。
ジョンスキート、

2
@ジョン、申し訳ありませんが、これを閉じる必要があります。
Tim Post

3
@ティム:十分に公正です-それはとにかくこれ以上の答えを得ていませんでした。個人的に私はそれを考えていた建設的になってしまう、あなたを気に-私は確かに人々がトリッキー見つけるものを見るすることが有用であることが判明。私はおそらく今それを尋ねなかっただろう...
ジョン・スキート

回答:


271

実行の遅延


12
Righto-これは明らかに読者の間でお気に入りです。これはこの質問にとって最も重要なことです。「バッファリングvsストリーミング」もミックスに追加します。これは密接に関連しているため、本で見たいほど詳細に説明されていないことが多いためです。
Jon Skeet

10
本当に?Linqの学習中に、怠惰な負荷の性質が何度も指摘されましたが、それは私にとって決して問題ではありませんでした。
Adam Lassek、

26
ALassekに同意します。MSDNのドキュメントには、LINQの遅延評価の性質が明記されています。多分本当の問題は開発者の怠惰なプログラミングの性質でしょう... =)
Seiti

4
...特にそれがLINQ to SQLではなくオブジェクトへのLINQに適用されることに気付いた場合-同じアイテムのリストをすでに列挙していて、リストは既に評価されました
Simon_Weaver

5
LINQを完全に理解するには、yieldステートメントとは何か、それがどのように機能するかを知ることが重要です。
peSHIr 2009年

125

延期された実行の概念が今では私に打ち負かされるべきだと知っていますが、この例は実際にそれを理解するのに本当に役立ちました:

static void Linq_Deferred_Execution_Demo()
{
    List<String> items = new List<string> { "Bob", "Alice", "Trent" };

    var results = from s in items select s;

    Console.WriteLine("Before add:");
    foreach (var result in results)
    {
        Console.WriteLine(result);
    }

    items.Add("Mallory");

    //
    //  Enumerating the results again will return the new item, even
    //  though we did not re-assign the Linq expression to it!
    //

    Console.WriteLine("\nAfter add:");
    foreach (var result in results)
    {
        Console.WriteLine(result);
    }
}

上記のコードは以下を返します。

Before add:
Bob
Alice
Trent

After add:
Bob
Alice
Trent
Mallory

2
blogs.msdn.com/b/charlie/archive/2007/12/09/…<-私の意見では、これは説明に最適なブログだと思います。(2007年をはるかに超えて、それがすでに長い間続いているとは信じられません)
Phill

104

言語に埋め込まれているのは単なる機能だけでLINQSQLなく、機能も単なるSQLパーサーではありません。


6
私は誰もがそれを考えることにうんざりしています:/
TraumaPony 2008年

40
誰もがそうとは限りません!私はまだLINQ to SQLが何であるかを知りません、そしてLINQをずっとずっと使用しています。
ロバートロスニー2008年

2
LINQを使用して何かを試して説明すると、私はとてもイライラします。他の人が私を見て、「ああ、LINQはそのようなものには使用しません。SQLだけです」と言います:(
Nathan W

13
多くの人々は、LINQが汎用ツールであることを理解していないようです。
マシューオレニク

86

ビッグオー表記。LINQを使用すると、何をしているのかわからない場合でも、O(n ^ 4)アルゴリズムを実現せずに非常に簡単に作成できます。


16
例はどうですか?
hughdbrown 2009年

4
例として、彼は、Select句に多くのSum()演算子を含めるのが非常に簡単で、レコードセット全体に別のパスを渡すことを意味している可能性があります。
Rob Packwood 2010年

1
実際、大きなO表記とは何か、なぜそれが重要なのか、結果として生じる非効率的なクエリの例を検討する価値があるかもしれません。それがオリジナルのポスターが示唆していたことだと思いますが、とにかくそれについて言及したいと思いました。-編集:この投稿が1.5歳だったことに気づきました:-)
zcrar70

7
それはO(n ^ x)ではなく、O(xn)です。
Malfist 2010年

3
結合演算子を使用せずに結合しようとすると、O(n ^ x)が発生します。 i2、i3、i4}。そして、私は実際にこれが以前に書かれたのを見ました。それは機能しますが、非常にゆっくりです。
MarkPflug、2011年

55

私は事実だと思いLambdaますが、同じ宣言渡すことができるように式は、式ツリーと匿名デリゲートの両方に解決することができますlambda両方に式をIEnumerable<T>拡張メソッドとIQueryable<T>拡張メソッドを。


2
同意した。私はベテランで、自分のQueryProviderを書き始めたときにこの暗黙のキャストが行われていることに気づきました
TheSoftwareJedi

53

連れて行ってくれたのような多くのLINQの拡張メソッドことを実現するためには長すぎるSingle()SingleOrDefault()などがラムダを取るオーバーロードを持っています。

できるよ :

Single(x => x.id == id)

これを言う必要はありません-いくつかの悪いチュートリアルは私に習慣をつけさせました

Where(x => x.id == id).Single()

+1、とてもいい。覚えておきます。
プレッツェル、

4
これも忘れてしまいます。これはCount()、特ににも当てはまります。コードの読みやすさの明らかなボーナスに加えて、パフォーマンスの違いがあるかどうかを知っていますか?
Justin Morgan

1
大学では、私の講師は、これらのオーバーロードを使用するためにポイントを取りたいと思いました!! 私は彼が間違っていることを証明しました!
TDaver

12
奇妙に聞こえるかもしれませんが、私は2番目の構文を好みます。私はそれがより読みやすいと思います。
コナミマン、2011

40

LINQ to SQLでは、DataContextを理解していない人々、それをどのように使用できるか、どのように使用すべきかを常に目にしています。永続オブジェクトではなく、作業単位オブジェクトであるDataContextを表示しない人が多すぎます。

操作ごとに新しい時間を作成するのではなく、DataContext /セッションit /などをシングルトン化しようとしている人がたくさんいます。

そして、IQueryableが評価される前にDataContextを破棄しますが、それは、DataContextよりもIQueryableを理解していない人にとってはより適切です。

私がよく混乱するもう1つの概念は、クエリ構文と式構文です。その時点で最も簡単な方法を使用します。多くの場合、式構文を使用します。最終的に同じものが生成されることをまだ多くの人はまだ認識していません。結局、Queryは式にコンパイルされます。


2
警告:作業単位は、データコンテキストをシングルトンとする小さなプログラムにすることができます。
08年

15
シングルトンではDataContextを使用しないでください。スレッドセーフではありません。
アーロンパウエル

3
@Slace、すべてのプログラムがマルチヘッドであるとは限らないため、DataContextを多くの「デスクトップ」ソフトウェアのシングルトンとして使用しても問題ありません
Ian Ringrose

2
私は最初のLINQ to SQLプロジェクトを実行したときに(DataContextをシングルトンとして使用して)噛み付きました。ドキュメンテーションと本がこれを十分に明白にするとは思いません。実は名前はもっと良くなると思いますが、どうすればいいのかわかりません。
Roger Lipscombe 2010

1
LinqでScottGuの記事を複数回読んで、これを頭の中で叩きました。
エヴァンプライス

34

私は思うLINQの誤解の一部は、それがあるということである言語拡張ではなく、データベースの拡張や構築物。

LINQはをはるかに超えていLINQ to SQLます。

私たちのほとんどがLINQコレクションに使用したので、決して戻ることはありません!

LINQ 2.0のジェネリックと3.0の匿名型以来、.NETの最も重要な機能の1つです。

ラムダを使用できるようになったので、並列プログラミングを待ちきれません。


私はそれを匿名型よりも、おそらくジェネリックよりももっと重要だとさえ呼びます。
Justin Morgan

26

私は、表現ツリーとは何か、そしてその理由を知る必要があるかどうかを知りたいと思っています。


6
式ツリーとは何か、なぜそれらが存在するのかを知ることは価値がありますが、それらを自分で構築する方法の詳細は知りません。(手作業でビルドするのは面倒ですが、ラムダ式を変換するときにコンパイラーは素晴らしい仕事をします。)
Jon Skeet

3
実際、式ツリーでいくつかのブログエントリを作成することを考えていました(それらを「取得」するため)。式ツリーの操作は非常に便利だと思います...
Marc Gravell

しかし、私はそれらがジョンの話に役立つとは思わない;-p
マークグラベル

3
表現ツリーが収量ステートメントのようになるのではないかと心配しているだけでした。最初は何を意味しているのか理解できなかったにも関わらず、信じられないほど貴重なものになりました。
ロバートロスニー2008年

1
Marc Gravellこの件に関するブログのエントリを読みたいです。それを楽しみにして
アレクサンドルブリセボワ

20

私はLINQにかなり慣れていません。これが私が最初の試みでつまずいたものです

  • 複数のクエリを1つに組み合わせる
  • Visual StudioでLINQクエリを効果的にデバッグします。

21
LINQのデバッグはそれ自体がトピックであり、重要なものです。LINQの最大の弱点は、ステップスルーできない任意の複雑なロジックのブロックを記述できることです。
ロバートロスニー2008年

3
これらはLINQパッドを使用するのに適した場所かもしれません
Maslow

2
心から同意します。それが私がLINQ Secrets Revealed:Chaining and Debuggingを書いた理由です。これはSimple-Talk.comで公開されたばかりであり、参考になるかもしれません。
Michael Sorens

はい、LinqPadはLINQクエリを開発するための優れた二次ツールです。特に、始めてコンベンション/パターンに慣れていない場合はそうです。
Buffalo

20

私が最初に気づかなかったことの1つは、LINQ構文必要としないIEnumerable<T>または機能しないことですIQueryable<T>。LINQはパターンマッチングに関するものです。

代替テキストhttp://bartdesmet.info/images_wlw/QIsIQueryabletheRightChoiceforMe_13478/image_thumb_3.png

ここに答えがあります(いいえ、私そのブログを書きませんでした、Bart De Smetが書きました、そして彼は私が見つけたLINQで最高のブロガーの一人です)。


1
あなたはあまりにも面白い、このブログの記事を見つけるかもしれない:msmvps.com/blogs/jon_skeet/archive/2008/02/29/...
ジョンスキート

いい投稿ジョン(私はあなたのブログを購読していますが、最近ですが)。
アーロンパウエル

19

「let」コマンド(使用法を見つけられませんでした)とSelectMany(使用したことはありますが、正しく実行したかどうかはわかりません)でまだ問題があります。


2
変数を導入したいときはいつでもletステートメントを使用します。内部に変数を導入し、コードを読みやすくするために各変数に名前を付ける従来のループについて考えてみましょう。関数の結果を評価するletステートメントがあり、結果を2回評価することなく選択して順番に並べることもできる場合があります。
Rob Packwood 2010年

'let'を使用すると、複合型を実行できます。便利なもの。
Phill、2010

19

Linqプロバイダー間の抽象化がいつリークするかを理解する。オブジェクトでは機能するものの、SQLでは機能しないものがあります(.TakeWhileなど)。一部のメソッドはSQL(ToUpper)に変換できますが、他のメソッドは変換できません。一部の手法はオブジェクトでより効率的であり、他の手法はSQLでより効果的です(異なる結合メソッド)。


1
これは非常に良い点です。Intellisenseがそれらすべてを表示し、通常はコンパイルすることもできません。次に、実行時に爆破します。私はVS 2010が関連する拡張メソッドを表示するより良い仕事をすることを望みます。
ジェイソンショート

12

いくつかのこと。

  1. LinqをSQLのLinqと考える人々。
  2. このパフォーマンスへの影響を考慮せずに、すべてのforeach / logicをLinqクエリに置き換えることができると考える人もいます。

11

ええ、需要があるので、Expressionに関するものをいくつか書きました。ブロガーとLiveWriterがどのようにフォーマットを作成したかについて100%満足しているわけではありませんが、今のところはうまくいきます...

とにかく、ここに行きます...特に人々がより多くの情報を求めている分野があるなら、私はどんなフィードバックも大好きです。

ここにあります、好きか嫌いか...


10

一部のエラーメッセージ、特にLINQからSQLへは、かなり混乱する可能性があります。にやにや

他の皆と同じように、私は延期実行に数回噛まれました。私にとって最も混乱しているのは、SQL Serverクエリプロバイダーと、それを使用してできることとできないことです。

空の10進数/金額の列でSum()を実行できないという事実には、今でも驚かされます。DefaultIfEmpty()を使用しても機能しません。:(


1
クエリでWhereを簡単に叩いて合計を機能させる
Pedersen

9

LINQで取り上げるべき素晴らしいことは、パフォーマンスの面でどのようにトラブルに巻き込まれるかです。たとえば、LINQのカウントをループ条件として使用することは、本当に賢くはありません。


7

そのIQueryableは、2番目のケースでのパフォーマンスの低下に関するヒントを与えることなく、Expression<Func<T1, T2, T3, ...>>との両方を受け入れFunc<T1, T2, T3, ...>ます。

これが私が何を意味するかを示すコード例です:

[TestMethod]
public void QueryComplexityTest()
{
    var users = _dataContext.Users;

    Func<User, bool>                funcSelector =       q => q.UserName.StartsWith("Test");
    Expression<Func<User, bool>>    expressionSelector = q => q.UserName.StartsWith("Test");

    // Returns IEnumerable, and do filtering of data on client-side
    IQueryable<User> func = users.Where(funcSelector).AsQueryable();
    // Returns IQuerible and do filtering of data on server side
    // SELECT ... FROM [dbo].[User] AS [t0] WHERE [t0].[user_name] LIKE @p0
    IQueryable<User> exp = users.Where(expressionSelector);
}

説明できますか?私はフォローしていません...
プレッツェル

@Pretzel私の問題を示すコード例を追加しました。
Valera Kolupaev

コード例をありがとう!非常に役立ちます。
Buffalo

6

誤解されているかどうかはわかりませんが、私にとっては、単に不明です。

DataLoadOptionsと、特定のクエリを実行するときに結合するテーブルを制御する方法について学ぶことができて嬉しく思います。

詳細については、こちらを参照してください:MSDN:DataLoadOptions


6

LINQの最も誤解されている(または理解されていないはずの)側面は、IQueryableおよびカスタムLINQプロバイダーです

私は今しばらくLINQを使用しており、IEnumerableの世界で完全に快適で、LINQのほとんどの問題を解決できます。

しかし、IQueryable、Expressions、およびカスタムlinqプロバイダーを調べて読み始めたとき、それは頭を悩ませました。かなり複雑なロジックを確認したい場合は、LINQ to SQLの動作を確認してください。

LINQのその側面を理解できることを楽しみにしています...


6

ほとんどの人が言ったように、最も誤解されている部分は、LINQがT-SQLの単なる置き換えであると想定していることだと思います。自分をTSQLの第一人者だと考える私のマネージャーは、私たちのプロジェクトでLINQを使用することを許可せず、そのようなものをリリースすることをMSさえ嫌っています!!!


TSQLの代わりに使用する人が多すぎます。彼らのほとんどは、実行計画について聞いたことがありません。
erikkallen 2009年

+1すべてのプロジェクトでLINQ to SQLを許可する限り、私はあなたのマネージャーに同意します。LINQ to Objectsはまったく別の問題です。
NotMe 2010

5

クエリが実行されたときにvarは何を表していますか?

それはiQueryableiSingleResultiMultipleResult、またはそれは実装に基づいて変化しません。C#での動的型付け(標準の静的型付け)と(静的な型)の使用については、いくつかの推測があります。


それはないですので、私の知る限りのvarが常に(それは匿名型だ場合でも)問題の具体的なクラスでないのIQueryable、ISingleResultや「I」(適用されない「I」が必要で始まる具象クラス)で始まるもの。
Motti

5

ループをネストするのがいかに簡単かは、誰もが理解しているとは思えません。

例えば:

from outerloopitem in outerloopitems
from innerloopitem in outerloopitem.childitems
select outerloopitem, innerloopitem

+1、おっと。それはかなり強力です。
プレッツェル

4

group by まだ私の頭を回転させます。

遅延実行に関する混乱は、いくつかの単純なLINQベースのコードをステップ実行し、ウォッチウィンドウで遊んでみることで解決できます。


1
楽しみのためにかなりのLINQ to Objectsを実装することは本当に役立つことがわかりました:)しかし、はい、それは少し混乱します-確かにしばらくLINQを実行していない場合、署名に戻る必要があります。同様に、「参加する」と「参加する」はしばしば私
ジョン・スキート

4

コンパイルされたクエリ

あなたはチェーンできないという事実IQueryable彼らは、メソッド呼び出し(しばらくしているので、まだ何もなく、SQLのtranslateable!)、それはmindbogglingとDRYの巨大な違反を作成しているの周りにそれが仕事にほとんど不可能であること。IQueryableコンパイルされたクエリがないアドホックのが必要です(重いシナリオのコンパイルされたクエリしかありません)が、コンパイルされたクエリでは使用できず、代わりに通常のクエリ構文を再度記述する必要があります。現在、2つの場所で同じサブクエリを実行しています。何か変更があった場合は、両方を更新することを忘れないでください。悪夢。


4

LINQ to SQLについての1番目の誤解は、SQLを効果的に使用するためにSQLを理解する必要があるということです。

Linq to Sqlについてもう1つの誤解されていることは、それを機能させるために、データベースのセキュリティを不合理なレベルまで下げる必要があることです。

3番目のポイントは、動的クラス(つまり、クラス定義が実行時に作成される)と共にLinq to Sqlを使用すると、膨大な量のジャストインタイムコンパイルが発生することです。これは絶対にパフォーマンスを低下させる可能性があります。


4
ただし、SQLをすでに知っていることは非常に有益です。Linq to SQL(および他のORM)によって生成される一部のSQLは実に疑わしい場合があり、SQLを知っているとそのような問題の診断に役立ちます。また、Linq to SQLはストアドプロシージャを利用できます。
Robert Harvey、


2

前述のように、遅延読み込みと遅延実行

LINQ to ObjectsおよびLINQ to XML(IEnumerable)とLINQ to SQL(IQueryable)の違い

HOWすべての層でLINQによるデータアクセス層、ビジネス層、およびプレゼンテーション層を構築....と良い例です。


私ができる最初の2つ。「これが正しい方法です」という意味で、まだ3番目を試してみたいとは思いません...
Jon Skeet

+1、あなたが指摘するまでは、LINQ-to-SQLとは対照的に、LINQ-to-ObjectsとLINQ-to-XMLがIEnumerableであることに気付いていませんでしたが、理にかなっています。ありがとう!
プレッツェル、

2

ほとんどの人が言ったように、最も誤解されている部分は、LINQがT-SQLの単なる置き換えであると想定していることだと思います。自分をTSQLの第一人者だと考える私のマネージャーは、私たちのプロジェクトでLINQを使用することを許可せず、そのようなものをリリースすることをMSさえ嫌っています!!!


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.