2011-09-21 14 views
17

Ho una classe di base che ha una proprietà virtuale:Quale eccezione si deve lanciare quando non è consentito un setter di proprietà?

public virtual string Name { get; set; } 

poi ho una classe derivata che prevale solo il getter della proprietà

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

Il problema è questo sostituisce solo il getter. Se qualcuno chiama il setter verrà chiamato il setter della base e il chiamante non saprà che è inefficace.

Così ho pensato di fare qualcosa di simile:

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

Quindi due (domande relative):

  1. C'è un modello migliore per me di utilizzare?
  2. Se dovrei usare lo schema sopra, quale eccezione usare?

Edit: Alcuni motivi per cui una sola eccezione sarebbe preferibile rispetto ad un altro sarebbe bene. Il mio collega ed io abbiamo avuto lo stesso argomento tra NotSupported e InvalidOperation.

+2

C'è una ragione per cui è necessario il setter nella classe base? –

+0

@DarylTeo sì, la classe base deve supportare l'impostazione manuale del nome, sebbene possa essere nel costruttore. – Ray

risposta

24

Eccezione NotSupportedException. Quota dal link:

Ci sono metodi che non sono supportati nella classe base, con il aspettativa che questi metodi saranno implementati nei derivati ​​ classi invece. La classe derivata potrebbe implementare solo un sottoinsieme di i metodi dalla classe base e lanciare NotSupportedException per i metodi non supportati.

La mia opinione è che InvalidOperationException non è un'opzione corretta. Citazione da MSDN:

L'eccezione generata quando una chiamata al metodo è valido per lo stato corrente dell'oggetto .

Non c'è nulla sullo stato attuale nella vostra situazione. È che il contratto di classe non supporta l'operazione.

+0

hm .. quella citazione ha un senso, anche se è un po 'l'opposto di quello che sto facendo. – Ray

+0

+1 La citazione è la risposta esatta alla domanda ed è come la sto facendo quando ho derivato le classi che non possono per qualche motivo implementare un metodo astratto –

+0

@Ray - Stai facendo esattamente lo stesso. Leggi di nuovo :) –

-3

Qui andrei per un NotImplementedException.

+10

-1 Questo segnala che non è ** ancora ** implementato, ma sta per. Il più delle volte, questo non è adatto alla produzione –

+0

Fair point. Spesso usato come eccezione di default per i generatori di codice. – Carra

7

Rompe il principio di sostituzione di Liskov ed è per questo che è una cattiva idea.

4

Se riesci, puoi provare a spostare setter su costruttore della classe base e rendere privato il setter. O come Jon ha suggerito di creare una classe/interfaccia di base astratta con getter che sono supportati in tutte le implementazioni.

Ciò eviterebbe l'intera situazione con l'eccezione di lancio.

1

Se la classe base consente effettivamente di impostare il nome (al contrario di esporre un setter astratto che non è garantito che funzioni), le classi derivate dovrebbero fare altrettanto.Se si desidera una gerarchia che include alcune classi in cui è possibile impostare il nome e alcuni in cui non è possibile, entrambi i tipi di classe devono ereditare da una classe astratta ReadableXX con una proprietà di lettura e scrittura non virtuale Name che esegue la catena per astrarre i metodi GetName e SetName . Dovrebbe anche fornire alcuni mezzi per indicare se sarà supportato SetName (ad esempio un metodo CanSetName). Una variante di sola lettura della classe potrebbe definire una "nuova" proprietà di sola lettura Name che va a catena a GetName e ha la sua sostituzione SetName da NotSupportedException. Se la specifica per la classe dice che SetName funzionerà solo se CanSetName restituisce true, quindi avere SetName generare un'eccezione nelle classi in cui CanSetName restituisce false non viola il Principio di sostituzione di Liskov.

Problemi correlati