web-dev-qa-db-fra.com

un arbre d'expression lambda ne peut pas contenir d'opérateur de propagation nul

Question : La ligne price = co?.price ?? 0, dans le code suivant me donne l'erreur ci-dessus. mais si je supprime ? de co.? cela fonctionne très bien. J'essayais de suivre cet exemple MSDN où ils utilisent ? en ligne select new { person.FirstName, PetName = subpet?.Name ?? String.Empty }; Il semble donc que j'ai besoin de comprendre quand utiliser ? avec ?? et quand ne pas le faire.

Erreur :

un arbre d'expression lambda ne peut pas contenir d'opérateur de propagation nul

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

L'exemple que vous avez cité utilise LINQ to Objects, où les expressions lambda implicites de la requête sont converties en délégués ... alors que vous utilisez EF ou similaire, avec IQueryable<T> queryies, où les expressions lambda sont converties en arbres d'expression. Les arbres d'expression ne prennent pas en charge l'opérateur conditionnel null (ou les nuplets).

Il suffit de le faire à l'ancienne:

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

(Je pense que l'opérateur à coalescence nulle convient parfaitement dans un arbre d'expression.)

89
Jon Skeet

Le code que vous associez utilise List<T>. List<T> implémente IEnumerable<T> mais pas IQueryable<T>. Dans ce cas, la projection est exécutée en mémoire et ?. fonctionne.

Vous utilisez des IQueryable<T>, qui fonctionnent très différemment. Pour IQueryable<T>, une représentation de la projection est créée et votre fournisseur LINQ décide quoi en faire lors de l'exécution. Pour des raisons de compatibilité avec les versions antérieures, ?. ne peut pas être utilisé ici.

Selon votre fournisseur LINQ, vous pourrez peut-être utiliser plain . sans toujours obtenir NullReferenceException.

6
user743382