2014-12-30 14 views
13

Leggendo molto sulla Null propagation operator ?., non ho trovato risposta se è utile nel seguente scenario.Operatore di propagazione null e foreach

codice che genera:

int[] values = null; 

foreach (var i in values) // Throws since values is null. 
{ 
    // ... 
} 

per rendere questo lavoro, devo aggiungere un controllo null prima che l'accesso alla variabile values.

Molto probabilmente il codice precedente non rientra nell'ambito delle considerazioni sulla progettazione per l'operatore di propagazione Null. Comunque, per essere sicuro, devo chiedere.

La mia domanda:

è l'operatore di propagazione Null utile quando si cerca di accedere a null raccolte in un ciclo foreach?

+7

Non una risposta, ma si potrebbe scrivere ' foreach (var i in valori ?? Enumerable.Empty ()) 'per evitare l'annidamento. –

+0

Oppure usa ArrayList o List invece :) – boctulus

+3

@Boctulus Anche questi sono tipi di riferimento nullable, sai?!? –

risposta

7

No, non lo è. È progettato per consentire l'accesso ai membri di un oggetto in modo sicuro. In questo caso è necessario verificare se l'array è null.

4

Come utilizzeresti?

Il codice che hai fornito:

int[] values = null; 

foreach (var i in values) 
{ 
    // ... 
} 

enxpands in qualcosa:

int[] values = null; 

var enumerator = values.GetEnumerator(); 
try 
{ 
    while (enumerator.MoveNext()) 
    { 
     var i = enumerator.Current; 
     // ... 
    } 
} 
finally 
{ 
    var disposable = enumerator as IDisposable; 
    if (disposable != null) 
    { 
     disposable.Dispose(); 
    } 
} 

Credo che si potrebbe scrivere qualcosa del genere:

int[] values = null; 

foreach (var i in values?.) 
{ 
    // ... 
} 

Il compilatore avrebbe per espanderla per qualcosa di simile:

int[] values = null; 

var enumerator = values?.GetEnumerator(); 
try 
{ 
    while (enumerator?.MoveNext() ?? false) 
    { 
     var i = enumerator.Current; 
     // ... 
    } 
} 
finally 
{ 
    var disposable = enumerator as IDisposable; 
    if (disposable != null) 
    { 
     disposable.Dispose(); 
    } 
} 

e hanno in mente che:

a = b?.M(); 

espande in:

a = b == null ? null : b.M(); 

Se si desidera di non scrivere in modo esplicito la dichiarazione if, si può sempre contare sul buon vecchio null-coalescing operator (??):

int[] values = null; 

foreach (var i in values ?? Enumerable.Empty<int>()) 
{ 
    // ... 
} 
+0

In questo modo: http: // stackoverflow. COM/a/31907661/7724 – bzlm

9

Ho trovato un altro modo di lavorare:

Quando si utilizza (et al) Fantastic MoreLinq estensioni di Jon Skeet, c'è un ForEach extension method che posso usare nel mio esempio iniziale come:

int[] values = null; 

values?.ForEach(i=> /*...*/); // Does not throw, even values is null. 
1

Per List<T> è possibile utilizzare list?.ForEach(i => ...); e per altri enumerables si può fare proprio interno PerOgni come questo:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) { 

    if (source == null) { return; } 

    foreach (T item in source) { 
     action(item); 
    } 
} 

si chiama così: myPossiblyNullEnumerable.ForEach(i => ...);

Se si desidera che l'estensione ForEach venga lanciata quando si invitano enumerables null, è sufficiente lasciare il controllo null e chiamarlo con la stessa sintassi elvis della versione List: myPossiblyNullEnumerable?.ForEach(i => ...);