2009-01-20 24 views
38

¿Cuál sería el mejor tipo de excepción para lanzar cuando se invoca un método de extensión en una instancia nula (donde el método de extensión no lo permite)? Dado que los métodos de extensión no son más que métodos estáticos, podría argumentar que debería ser ArgumentNullException, pero por otro lado se usan como métodos de instancia, por lo que podría ser más natural usar la NullReferenceException. Tomemos el siguiente ejemplo:ArgumentNullException o NullReferenceException del método de extensión?

public static string ToInvariantString(this IFormattable value, string format) 
{ 
    return value.ToString(format, CultureInfo.InvariantCulture); 
} 

esta manera una NullReferenceException se produce si el parámetro valor es nulo.

El otro ejemplo sería:

public static string ToInvariantString(this IFormattable value, string format) 
{ 
    if (value == null) throw new ArgumentNullException("value"); 
    return value.ToString(format, CultureInfo.InvariantCulture); 
} 

EDIT: En algunas de las respuestas que han señalado que un métodos de extensión se puede llamar como un método estático y en esos casos una excepción de referencia nula estaría mal, lo cual es un gran punto, y en realidad una de mis preocupaciones, no estoy seguro de por qué me olvidé de mencionar eso en la pregunta en primer lugar.

Alguien también señaló que es incorrecto lanzar una NullReferenceException, y sí, lo es. Es por eso que no lo tiro, simplemente dejo que suceda (deje que CLR lo lance) al no guardar el método.

Creo que estoy a favor de ArgumentNullException (eso es lo que he usado hasta ahora) pero sigo pensando que hay al menos espacio para argumentar en contra de la NullReferenceException ya que parece más natural en la mayoría de los lugares donde el método va a ser usado.

Respuesta

34

En general, con excepciones incluidas, debe tratar un método de extensión como si fuera un método estático normal. En este caso, debe lanzar una ArgumentNullException.

Lanzar un NullReferenceException aquí es una mala idea por varias razones

  • una referencia nula en realidad no ocurren así que ver uno es contrario a la intuición
  • Lanzar un NullReferenceException y causando una NullReferenceException que se produzca producir discerniblemente diferentes excepciones (Una forma de ver la diferencia es el código de error). Esto es cierto de muchas excepciones que arroja el CLR.

Ver When can you catch a StackOverflowException (una publicación que hice sobre este tema).

  • Es perfectamente legal llamar a un método de extensión como si fuera un método normal. En ese caso, ciertamente no exceptuaría una NullReferenceException, sino una ArgumentNullException.
+0

Excelentes comentarios y, como mencioné en mi edición de la publicación, esta es la razón por la que no lanzo explícitamente la NullReferenceException, todavía dejo que la CLR la emita. –

+0

"No se produjo realmente una referencia nula". Sí lo hizo; pasaste una referencia nula y el método intentó desreferenciarla. – piedar

+0

@piedar el método intentó desreferenciarlo, ¡no el tiempo de ejecución! –

1

Desde el punto de vista del usuario, el método se ve y actúa como un método de instancia, por lo que si yo fuera ellos, esperaría ver una NullReferenceException.

Dicho esto, sugeriría arrojar uno u otro explícitamente en el código, en lugar de simplemente "pasar" para arrojar uno como en su primer ejemplo.

+0

Sí, he pensado en lanzar explícitamente la NullReferenceException, pero mi sensación es que debería estar reservada para el compilador realmente, pero es posible que tengas razón. –

+2

Desde el punto de vista de un usuario, se puede llamar a un método de extensión tanto por extensión como como método estático. – JaredPar

1

ArgumentNullException. Hay no requisito para llamar a los métodos de extensión como si fueran métodos de instancia. Puede llamarlos como si fueran métodos normales. NullReferenceException sería completamente incorrecto en ese caso.

6

Dado que los métodos de extensión se pueden usar en C# 2.0, y se pueden llamar como métodos estáticos (NO TIENE que usarlos como métodos de extensión), debe usar ArgumentNullException.

El hecho de que mira como los métodos sobre el tipo no significa que son, o siempre se llaman como uno.

19

Aparte de todas las otras respuestas (que son buenos) Creo que vale la pena mirar lo que Microsoft hace por razones de coherencia ... y los métodos de extensión en toda Enumerable tiro ArgumentNullException Por lo que yo puedo ver.

+0

¡Gran idea, tuve eso yo mismo, no lo hice, no estoy seguro de por qué! ;-) –

+1

Esta es una técnica útil que uso muy a menudo. Sin embargo, uno siempre debe tener en cuenta que el hecho de que FCL utilice un método particular para lograr algo, no significa que el método sea óptimo o correcto. Recomiendo pensar en los métodos FCL como sugerencias sobre cómo lograr algo, pero el mérito de un método dado debe compararse con las alternativas antes de juzgar si es la mejor opción. –

Cuestiones relacionadas