web-dev-qa-db-ja.com

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

Question:次のコードのprice = co?.price ?? 0,行に上記のエラーが表示されます。しかし、?からco.?を削除すると、問題なく動作します。従おうとしていました このMSDNの例?select new { person.FirstName, PetName = subpet?.Name ?? String.Empty };を使用している場所です。したがって、???およびそうでない場合。

エラー

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

public class CustomerOrdersModelView
{
    public string CustomerID { get; set; }
    public int FY { get; set; }
    public float? price { get; set; }
    ....
    ....
}
public async Task<IActionResult> ProductAnnualReport(string rpt)
{
    var qry = from c in _context.Customers
              join ord in _context.Orders
                on c.CustomerID equals ord.CustomerID into co
              from m in co.DefaultIfEmpty()
              select new CustomerOrdersModelView
              {
                  CustomerID = c.CustomerID,
                  FY = c.FY,
                  price = co?.price ?? 0,
                  ....
                  ....
              };
    ....
    ....
 }
61
nam

引用した例では、LINQ to Objectsを使用しています。クエリ内の暗黙的なラムダ式はデリゲート ...に変換されますが、EFまたは類似のIQueryable<T> queryiesを使用している場合、ここで、ラムダ式はexpression treesに変換されます。式ツリーは、null条件演算子(またはタプル)をサポートしていません。

古い方法で実行してください:

price = co == null ? 0 : (co.price ?? 0)

(ヌル合体演算子は式ツリーでは問題ないと思います。)

89
Jon Skeet

リンクするコードはList<T>を使用します。 List<T>IEnumerable<T>を実装しますが、IQueryable<T>は実装しません。その場合、投影はメモリ内で実行され、?.が機能します。

いくつかのIQueryable<T>を使用していますが、動作は非常に異なります。 IQueryable<T>の場合、投影の表現が作成され、LINQプロバイダーが実行時にそれをどう処理するかを決定します。後方互換性の理由により、?.はここでは使用できません。

LINQプロバイダーによっては、プレーン.を使用できても、NullReferenceExceptionを取得できない場合があります。

6
user743382