ラムダ式でnull伝播演算子を使用できないのはなぜですか?


102

私はコードでnull伝播演算子をよく使用します。コードが読みやすくなるためです。特に、長いクエリでは、使用されるすべてのクラスをnullチェックする必要がないためです。

次のコードは、ラムダでnull伝播演算子を使用できないコンパイルエラーをスローします。

var cnt = humans.AsQueryable().Count(a => a.House?[0].Price == 5000);

エラー :

エラーCS8072式ツリーのラムダにnullの伝播演算子を含めることはできません。

C#は、実際には他に何もできない場合、上記のコードを次のコードに簡単に変換できます。

var cnt = humans.AsQueryable().Count(a => a.House != null && a.House[0].Price == 5000);

C#が何もせず、単にコンパイラエラーをスローするのはなぜでしょうか。


4
Foo?.Barは、null伝播演算子で1回、条件付きで2回評価されるFoo != null ? Foo.Bar : nullため、同等ではありませんFoo。したがって、すべての場合で変換は正しくありません。
Lucas Trzesniewski、2015年

3
EFのコードの場合、クエリがSQL呼び出しに変換されてもSQLがnullをスローしないため、null伝播演算子が実際には不要である可能性があることに注意してください:-)
xanatos

注意:現在、EFはオペレーターをサポートしていないため、var q = from c in Categories join p in Products on c equals p.Category into ps from p in ps.DefaultIfEmpty() select new { Category = c, ProductName = (p?.ProductName)??"(No products)"};書く必要はなく、書くことも有用です。ProductName = (p == null) ? "(No products)" : p.ProductName?.
Matt

回答:


72

式ツリーのラムダ(デリゲートラムダとは異なります)は、null伝播をまだサポートしていない既存のLINQプロバイダーによって解釈されるため、複雑です。

複数の評価があるため、条件式への変換は必ずしも正確ではありませんが、評価?.は1つしかないため、たとえば次のようになります。

customer.Where(a => c.Increment()?.Name) // Written by the user 
customer.Where(a => c.Increment() == null ? null : c.Increment().Name) // Incorrectly interpreted by an old LINQ provider

あなたは、関連してより深く行くことができCodePlexの上の議論 3つのソリューションが提供されています:NullPropagationExpressionConditionalExpression&ハイブリッド


23
特定のクエリプロバイダーがそれをサポートできなくても、私は確かに驚かないでしょうが、それがC#言語でサポートされていない理由ではありません。
サービー2015年

16
特定のクエリプロバイダーがまだそれをサポートしていないという事実は、すべてのクエリプロバイダーがこれを使用できるようにすることを禁止する理由ではありません。
Servy

10
そしてもちろん、そのプロバイダーのユーザーが実際にそれを表す式ツリーを作成できるようになるまで、そのような要求の処理をサポートするために時間をかけるクエリプロバイダーはありません。これをサポートするために、最初に起こる必要があるのは、ラムダがそれを表現できるようにすることです。 それが存在するようになると、クエリプロバイダーは、適切だと感じたときに、サポートを開始できます。また、さまざまなことを行うプロバイダーもたくさんあります。EFが世界で唯一のクエリプロバイダーであるようではありません。
Servy

7
全体のポイントは、ExpressionすべてのC#式をコードとして意味的に表現できることです。言語の小さなサブセットになるようには設計されていません。
サービー2015年

6
3年経ってもこれはまだ解決されていないようです。Microsoftが今までに時間を見つけることができなかったのではないでしょうか。最近、C#で新しい機能を半分実装するための言い訳として、時間とリソースを使用するという悪い癖があるようです。
NetMage 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.