2011-09-21 7 views
17

I tienen una clase base que tiene una propiedad virtual:¿Qué excepción arrojar cuando no se permite un ajustador de propiedades?

public virtual string Name { get; set; } 

entonces tengo una clase derivada que anula sólo el getter de la propiedad

public override string Name 
{ 
    get { return "Fixed Name"; } 
} 

El problema es que esto sólo anula el getter. Si alguien llama al colocador, se llamará al clasificador de la clase base y la persona que llama no sabrá que es ineficaz.

así que pensé que haría algo como:

public override string Name 
{ 
    get { return "Fixed Name"; } 
    set { throw new Exception(); } //which exception type? 
} 

Así que dos (preguntas relacionadas):

  1. ¿Hay un mejor patrón para que yo use?
  2. Si debería usar el patrón anterior, ¿qué excepción usar?

Editar: Algunas razones por las que una excepción sería preferible a otra sería buena. Mi compañero de trabajo y yo hemos tenido el mismo argumento entre NotSupported y InvalidOperation.

+2

¿Hay alguna razón por la que necesite el colocador en la clase base? –

+0

@DarylTeo sí, la clase base debe admitir la configuración del nombre de forma manual, aunque podría estar en el constructor. – Ray

Respuesta

24

Tirar NotSupportedException excepción. Cita del enlace:

Hay métodos que no son compatibles en la clase base, con la expectativa de que estos métodos se llevarán a cabo en las clases derivadas en su lugar. La clase derivada podría implementar solo un subconjunto de los métodos de la clase base, y lanzar NotSupportedException para los métodos no compatibles.

Mi opinión es que InvalidOperationException no es una opción correcta. Presupuesto de MSDN:

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

No hay nada sobre el estado actual en su situación. Es que el contrato de clase no admite la operación.

+0

hm .. esa cita tiene sentido, aunque es algo opuesto a lo que estoy haciendo. – Ray

+0

+1 La cita es la respuesta exacta a la pregunta y es la forma en que lo hago cuando obtuve clases que no pueden, por alguna razón, implementar un método abstracto –

+0

@Ray - Usted está haciendo exactamente lo mismo. Léelo de nuevo :) –

-3

Aquí iría por un NotImplementedException.

+10

-1 Esto indica que aún no está ** implementado **, pero va a hacerlo. La mayoría de las veces, esto no es adecuado en la producción –

+0

Fair point. A menudo se usa como una excepción predeterminada para generadores de código. – Carra

7

Rompe el Principio de Sustitución de Liskov y es por eso que es una mala idea.

4

Si puede, podría intentar mover setter a constructor de la clase base y hacer que setter sea privado. O como Jon sugirió crear una clase base/interfaz abstracta con getters que son compatibles con todas las implementaciones.

Esto evitaría toda la situación con tirar la excepción.

1

Si la clase base realmente permite establecer el nombre (en lugar de exponer un resumen que no se garantiza que funcione), las clases derivadas deberían hacerlo también.Si desea una jerarquía que incluya algunas clases donde el nombre puede establecerse y otras donde no, ambos tipos de clase deben heredar de una clase abstracta ReadableXX con una propiedad de lectura-escritura no virtual Name que encadena a los métodos abstractos GetName y SetName . También debe proporcionar algunos medios para indicar si se admitirá SetName (por ejemplo, un método CanSetName). Una variante de solo lectura de la clase podría definir una "nueva" propiedad de solo lectura Name que encadena a GetName, y tiene su SetName anulación de tiro NotSupportedException. Si la especificación de la clase dice que SetName solo funcionará si CanSetName devuelve verdadero, entonces tener SetName lanzar una excepción en las clases donde CanSetName devuelve falso no violaría el Principio de sustitución Liskov.

Cuestiones relacionadas