Domanda

Di seguito è riportato un codice di prova LINQPad. Quando questo viene eseguito esso errori perché la seconda istanza di "elemento" ha una lista nulla di elementi secondari rispetto a una lista vuota.

Voglio trattare entrambe le situazioni (elenco nullo o vuoto) esattamente nello stesso modo, ma mi chiedevo se ci fosse un modo più pulito di mettere semplicemente in un controllo nulla sulla lista e inizializzazione un elenco vuoto quando c'è un nullo.

In altre parole, avrei potuto fare questo:

from si in (i.subitems == null ? new List<item>() : i.subitems)

ma questo è un po 'brutto e mi chiedevo come avrei potuto migliorare su questo?

public class item
{
    public string itemname { get; set; }
    public List<item> subitems { get; set; }
}

void Main()
{
    List<item> myItemList = new List<item>() 
    {
        new item 
        {
            itemname = "item1",
            subitems = new List<item>()
            {
                new item { itemname = "subitem1" },
                new item { itemname = "subitem2" }
            }
        },
        new item 
        {
            itemname = "item2"
        }
    };

    myItemList.Dump();

    var res = (from i in myItemList
            from si in i.subitems
            select new {i.itemname, subitemname = si.itemname}).ToList();

    res.Dump();
}

come una questione bonus, può questa stessa query LINQ essere rappresentato come un lambda e trattare i null allo stesso modo?

Saluti, Chris

È stato utile?

Soluzione

È possibile utilizzare il nullo coalescenza operatore

var res = (from i in myItemList
           from si in i.subitems ?? new List<item>()
           select new { i.itemname, subitemname = si.itemname }).ToList();

Ma penso che si dovrebbe solo filtrare i vuoti fuori

var res = (from i in myItemList
           where i.subitems != null
           from si in i.subitems
           select new { i.itemname, subitemname = si.itemname }).ToList();

Per quanto riguarda una versione lambda si potrebbe dire

var res = myItemList.Where(x => x.subitems != null)
                    .SelectMany(
                        x => x.subitems.Select(
                            y => new { x.itemname, subitemname = y.itemname }
                        )
                     );

Ma la versione sintassi di query è il modo più readble.

Altri suggerimenti

from si in (i.subitems ?? new List<item>())

Che ne dici?

Si potrebbe aggiungere una (male) metodo di estensione per fare il lavoro per voi

public static IEnumerable<T> EnsureNotEmpty<T>(this IEnumerable<T> enumerable) {
  if ( enumerable == null ) {
    return Enumerable.Empty<T>();
  } else { 
    return enumerable;
  }
}

Un ulteriore metodo sarebbe di non permettere elementi secondari di essere nulla. Si potrebbe fare il costruttore elemento in modo che il valore predefinito elemento secondario ad una lista vuota e quindi non consentono nullo nel setter sottovoce.

Questo naturalmente presuppone che l'accesso per modificare oggetto.

L'operatore null coalescenza è quello che stai cercando, come sottolineato da Hunter Daley

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top