Come devo trattare liste nulli come le liste vuote in LINQ?
-
18-09-2019 - |
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
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