Así que con frecuencia me encuentro con esta situación ... donde Do.Something(...)
devuelve una colección nula, así:
int[] returnArray = Do.Something(...);
Entonces, trato de usar esta colección así:
foreach (int i in returnArray)
{
// do some more stuff
}
Solo tengo curiosidad, ¿por qué un bucle foreach no puede funcionar en una colección nula? Me parece lógico que 0 iteraciones se ejecuten con una colección nula ... en su lugar, arroja un NullReferenceException
. Alguien sabe por qué esto podría ser?
Esto es molesto ya que estoy trabajando con API que no tienen claro exactamente lo que devuelven, así que termino en if (someCollection != null)
todas partes ...
Editar: Gracias a todos por explicar esos foreach
usos GetEnumerator
y si no hay un enumerador para obtener, el foreach fallará. Supongo que estoy preguntando por qué el lenguaje / tiempo de ejecución no puede o no hará una comprobación nula antes de tomar el enumerador. Me parece que el comportamiento aún estaría bien definido.
null
valor. ¿Sugieres esto solo paraforeach
bucles u otras declaraciones?Respuestas:
Bueno, la respuesta corta es "porque así lo diseñaron los diseñadores del compilador". Sin embargo, de manera realista, su objeto de colección es nulo, por lo que no hay forma de que el compilador haga que el enumerador recorra la colección.
Si realmente necesita hacer algo como esto, pruebe el operador de fusión nula:
fuente
GetEnumerator
el resultadoUn
foreach
bucle llama alGetEnumerator
método.Si la colección es
null
, esta llamada al método da como resultado aNullReferenceException
.Es una mala práctica devolver una
null
colección; sus métodos deberían devolver una colección vacía en su lugar.fuente
int[] returnArray = Do.Something() ?? new int[] {};
... ?? new int[0]
.Hay una gran diferencia entre una colección vacía y una referencia nula a una colección.
Cuando usa
foreach
, internamente, esto llama al método GetEnumerator () de IEnumerable . Cuando la referencia es nula, esto generará esta excepción.Sin embargo, es perfectamente válido tener un
IEnumerable
o vacíoIEnumerable<T>
. En este caso, foreach no "iterará" sobre nada (ya que la colección está vacía), pero tampoco lanzará, ya que este es un escenario perfectamente válido.Editar:
Personalmente, si necesita solucionar esto, le recomiendo un método de extensión:
Entonces puede simplemente llamar:
fuente
Se está respondiendo desde hace mucho tiempo, pero he intentado hacer esto de la siguiente manera para evitar una excepción de puntero nulo y puede ser útil para alguien que usa el operador de verificación nula de C #.
fuente
null
) generalizar todo el ciclo a la pantalla LCD deEnumerable
(como se??
usaría), b) requiere agregar un Método de Extensión a cada Proyecto, y c) requieren evitarnull
IEnumerable
s (Pffft! Puh-LEAZE! SMH.) para empezar.Otro método de extensión para evitar esto:
Consumir de varias maneras:
(1) con un método que acepta
T
:(2) con una expresión:
(3) con un método anónimo multilínea
fuente
Console.WriteLine
es solo un ejemplo de un método que toma un argumento (anAction<T>
). Los elementos 1, 2 y 3 muestran ejemplos de pasar funciones al.ForEach
método de extensión.null
) generalizando todo el bucle a la pantalla LCD deEnumerable
(como se??
usaría) ), b) requieren agregar un Método de Extensión a cada Proyecto, o c) requieren evitarnull
IEnumerable
s (Pffft! Puh-LEAZE! SMH.) para comenzar con (cuz,null
significa N / A, mientras que la lista vacía significa que es aplicable, pero es actualmente, bueno, ¡ vacío !, es decir, un Empl. podría tener Comisiones que son N / A para no ventas o vacías para Ventas).Simplemente escriba un método de extensión para ayudarlo:
fuente
Porque una colección nula no es lo mismo que una colección vacía. Una colección vacía es un objeto de colección sin elementos; Una colección nula es un objeto inexistente.
Aquí hay algo para probar: declara dos colecciones de cualquier tipo. Inicialice uno normalmente para que esté vacío y asigne al otro el valor
null
. Luego intente agregar un objeto a ambas colecciones y vea qué sucede.fuente
Es culpa de
Do.Something()
. La mejor práctica aquí sería devolver una matriz de tamaño 0 (que es posible) en lugar de un valor nulo.fuente
Porque detrás de escena
foreach
adquiere un enumerador, equivalente a esto:fuente
null
referencias, por ejemplo, al acceder a los miembros. Por lo general, este es un error, y si no lo es, es lo suficientemente simple como para manejar esto, por ejemplo, con el método de extensión que otro usuario ha proporcionado como respuesta.Creo que la explicación de por qué se produce una excepción es muy clara con las respuestas proporcionadas aquí. Solo deseo complementar con la forma en que suelo trabajar con estas colecciones. Porque, algunas veces, uso la colección más de una vez y tengo que probar si es nula cada vez. Para evitar eso, hago lo siguiente:
De esta manera, podemos usar la colección todo lo que queramos sin temor a la excepción y no contaminamos el código con declaraciones condicionales excesivas.
Usar el operador de verificación nula
?.
también es un gran enfoque. Pero, en caso de matrices (como el ejemplo en la pregunta), debe transformarse en Lista antes:fuente
ForEach
método es una de las cosas que odio en una base de código.fuente