2011-01-07 15 views
7

Lo typeo de excepción sería tirar de una propiedad de sólo lectura cuando el objeto que se utiliza para devolver el valor es nulo¿Qué tipo de excepción a tirar

public class TestClass 
{ 
    SomeObject obj; 
    public string NameOfObject 
    { 
     get 
     { 
      if(obj == null) 
      { // what exception type to throw here } 
      return obj.Name; 
     } 
} 
+2

Quizás esta es una pregunta por su tema, pero ¿por qué lanzar uno? – 4imble

+0

IMPORTANTE Nota: Una propiedad debe (casi) NUNCA lanzar una excepción cuando se lee. (InvalidOperation es uno que puede tho). http://msdn.microsoft.com/en-us/library/bb386039.aspx – FastAl

Respuesta

7

Un InvalidOperationException es lo que usaría en este caso, porque el acceso a la propiedad no es válido para el estado actual del objeto.

De acuerdo con la documentación de MSDN:
"La excepción que se produce cuando una llamada al método no es válida para el estado actual del objeto."
también:
"InvalidOperationException se utiliza en los casos en los que la falta de invocación de un método se debe a razones distintas de los argumentos no válidos."

En este caso obj no es un argumento, por lo que me gustaría inclinarse hacia "InvalidOperationException"

La razón por la que no volvería a lanzar una NullReferenceException aquí: Si que aún no ha agregado algún código especial, esa es la excepción que ".Net" arrojaría, ¿por qué agregar código redundante?

2

A menos que usted está diciendo en alguna parte que esta propiedad nunca lo hará ser nulo, ¿por qué necesitarías lanzar una excepción?

Dicho esto, si usted lo ha garantizado, arrojaría un InvalidOperationException.

InvalidOperationException es

La excepción que se produce cuando una llamada método es válido para el estado actual del objeto .

9

Yo arrojaría un InvalidOperationException.

ArgumentNullException i solo arrojar si los parámetros de los métodos son nulos.

Si el parámetro de métodos está en un estado inválido arrojo un ArgumentException.

+3

Si hace 'nueva InvalidOperationException()' sin pasar su propio mensaje, el mensaje predeterminado es "La operación no es válida debido al estado actual de el objeto. ", que es exactamente correcto. –

+0

+1 para las informaciones detalladas;) – Khh

4

No debe lanzar NullReferenceException. Está reservado para situaciones cuando un objeto nulo es desreferenciado. En este caso, si lanzas NullReference, también puedes dejar el check nulo y dejar que el framework lo lance cuando intentes acceder al Nombre del obj.

Yo lanzaría InvalidOperationException en su lugar.

+0

+1 para la explicación de por qué no se usa una NullReferenceException – Khh

1

me tiraría un InvalidOperationException, pero sólo si: - Es legal que obj para ser null, y es responsabilidad del usuario para comprobar esto, o - no es legal para obj para ser null en el primer lugar (es decir, obj != null es un invariante de clase)

Si ninguno de los anteriores es el caso (es decir, es legal para obj para ser null, y el código de usuario no se requiere explícitamente para comprobar esto antes de usar la propiedad), entonces no lanzaría nada, sino que devolvería null.

1

Volvería a visitar el diseño para que este estado no pueda existir en primer lugar, es decir, obj es nulo. En general, desde una perspectiva de API, debe poder llamar a un getter de buena fe para que no explote como resultado de que el objeto se encuentre en un estado desconocido.

Por ejemplo, ¿por qué no tener 'SomeObject obj' como un parámetro de constructor y usar la validación de argumentos en el punto de construcción? Esto asegurará que el estado de 'obj' sea siempre correcto, es decir, no nulo después de la construcción.

Hay muchos patrones que se pueden utilizar para garantizar que un objeto tenga un estado correcto cuando esté disponible para el usuario.

2

Todo el mundo ha cubierto lo obvio, así que aquí hay otra opción.

Si su clase debe inicializarse de alguna manera (su SomeObject debe establecerse en algún momento), considere implementar ISupportInitialize. Esto indica a los usuarios de su clase que no se encuentra en un estado válido antes de llamar al EndInit(). Desafortunadamente, no existe un NotInitializedException general preexistente que pueda usar (hay algunos pero son específicos de ciertos espacios de nombres), por lo que le sugiero que empareje su implementación de la interfaz con la creación de dicha excepción.

Los usuarios deben primero llamar al BeginInit(), luego configurar la instancia, luego llamar al EndInit(). En la llamada al EndInit(), verifique el estado de su instancia. Si no se inicializa correctamente, puede arrojar una InvalidOperationException. Si los usuarios intentan usar su instancia antes de inicializarse, lanzarían su NotInitializedException.

Trabaja un poco más, pero la ventaja es que está creando un "pozo de éxito" más amplio para sus usuarios, asegurándose de que usan sus clases correctamente al fallar rápido y temprano, y por la definición de su tipo (la interfaz es bastante clara en lo que esperas). También le da más "espacio", por así decirlo, para documentar cómo debe usarse su clase.

+0

Estoy familiarizado con ISupportInitialize y su uso en contextos DI (es decir, inyección de propiedad). No estoy tan seguro de que esto funcione tan bien como una API programática \ usuario. Este patrón se usa mucho en WinForms y WPF, pero sospecho que pocas personas lo saben, por lo que no estoy tan seguro del ángulo del 'pozo del éxito'. Este patrón se usa en marcos de interfaz de usuario debido a la necesidad de un constructor predeterminado. En una API de usuario, esto no necesariamente tiene que ser el caso, se pueden usar otros mecanismos para garantizar que un objeto se crea con el estado correcto, p. parámetros de constructor y validación arg. –

+1

@chi todo cierto. Pensé que incluso después de quince respuestas de "InvalidOperationException", había espacio para al menos una alternativa. El pozo es más grande, porque obliga a los usuarios a "configurar" la instancia, lo que significa que los usuarios deben considerar lo que realmente significa.Es un poco más claro que este o aquel método/propiedad lanzando una excepción si aún no has hecho algo. – Will

+0

Estoy de acuerdo: creo que hay mejores formas de resolver el problema que lanzar una "InvalidOperationException". También estaba en el ángulo de solución alternativa. –

1

Mirando el código que proporciona y sin saber nada sobre sus suposiciones de diseño, diría que no debe probar obj == null y deje que el marco arroje un NullReferenceException. Entonces, ¿por qué quieres esta prueba? Una razón por la que podría pensar es que desea tener un mensaje de error más significativo para la depuración, pero luego debe usar Debug.Assert(obj != null, "Your message here").

Cuestiones relacionadas