Tipo eccellente di eccezione astratta


17

Se il lancio System.Exceptionè considerato così male, perché non è stato Exceptionfatto abstractin primo luogo?

In questo modo, non sarebbe possibile chiamare:

throw new Exception("Error occurred.");

Ciò imporrebbe l'uso di eccezioni derivate per fornire maggiori dettagli sull'errore che si è verificato.

Ad esempio, quando voglio fornire una gerarchia di eccezioni personalizzata per una libreria, di solito dichiaro una classe base astratta per le mie eccezioni:

public abstract class CustomExceptionBase : Exception
{
    /* some stuff here */
}

E poi alcune eccezioni derivate con uno scopo più specifico:

public class DerivedCustomException : CustomExceptionBase
{
    /* some more specific stuff here */
}

Quindi quando si chiama qualsiasi metodo di libreria, si potrebbe avere questo generico blocco try / catch per rilevare direttamente qualsiasi errore proveniente dalla libreria:

try
{
    /* library calls here */
}
catch (CustomExceptionBase ex)
{
    /* exception handling */
}

È una buona pratica?

Sarebbe bello se Exceptionfosse reso astratto?

EDIT: Il mio punto qui è che anche se una classe di eccezione è contrassegnata abstract, puoi ancora prenderla in un blocco catch-all. Renderlo astratto è solo un modo per vietare ai programmatori di lanciare un'eccezione "super ampia". Di solito, quando si lancia volontariamente un'eccezione, è necessario sapere che tipo è e perché è successo. Pertanto, imponendo di lanciare un tipo di eccezione più specifico.


3
+1 "Il modo migliore per prevenire un uso errato è di renderlo impossibile." - Scott Meyers
Steven Jeuris,

3
"Sarebbe bello se l'eccezione fosse resa astratta?" - Assolutamente no, perché tutto il codice .NET esistente che utilizza la nuova eccezione ("...") si spezzerebbe. Tuttavia, "Il team di .NET avrebbe dovuto rendere astratta l'eccezione per cominciare?" - probabilmente sì, ma ormai è> 10 anni troppo tardi :)
MattDavey,

Risposte:


11

Non conosco i motivi reali per cui è stato fatto in questo modo, e in una certa misura concordo sul fatto che impedire che vengano emesse eccezioni infondatamente ampie sarebbe una buona cosa.

MA ... quando si codificano piccole app demo o prove di concetti, non voglio iniziare a progettare 10 diverse sottoclassi di eccezioni o passare il tempo a cercare di decidere quale sia la "migliore" classe di eccezioni per la situazione. Preferirei semplicemente lanciare Exceptione passare una stringa che spiega i dettagli. Quando è il codice usa e getta, non mi importa di queste cose e se sono stato costretto a prendersi cura di queste cose, mi piacerebbe creare sia la mia GenericExceptionclasse e gettare che in tutto il mondo, o il passaggio ad un diverso strumento / lingua. Per alcuni progetti, sono d'accordo sul fatto che la creazione di sottoclassi di eccezione pertinenti sia importante, ma non tutti i progetti lo richiedono.


Sono completamente d'accordo con te, ma la domanda stava implicitamente pensando a progetti non banali.
marco-fiset,

3

Possibilità A: è logicamente corretto.

Hai ragione sul fatto che Microsoft, insieme a molti altri, non suggerisce di lanciare new Exception()direttamente una serie di ragioni.

Detto questo, possiamo considerare l'ideale accademico secondo cui lo scopo di una Exceptiongerarchia di classe è definire un effetto restrittivo in modo che possano essere colte solo le eccezioni più specifiche. (cioè ArgumentNullExceptionè più stretto di ArgumentException).

La classe Exception non fa eccezione (gioco di parole non previsto). È intesa come la più ampia eccezione possibile, una "super eccezione" che quasi non può essere colta perché il suo campo di applicazione è infinitamente ampio. 'Eccezione' non è abstractnel senso che l'eccezione non può esistere come entità da sola. Può (anche se non è ancora stato definito alcun caso valido - si veda la possibilità B), e quindi dovrebbe essere pubblicamente costruibile.

La parola chiave "astratta" (in senso puramente accademico) è applicabile solo quando la classe base non ha senso da sola - vale a dire FourLeggedAnimal .

Tutto ciò in mente, non ci sarebbe alcun motivo tecnico per rendere la classe abstract, se non quella di essere una fonte di aggravamento per gli sviluppatori .

Possibilità B: Design Lock-in / Non lo sapevano

Se la SM rendesse astratta questa classe, potrebbero essersi trovati nei guai se avessero cambiato idea lungo la strada, poiché questa classe è molto essenziale per i fondamenti della lingua. Hanno già preso in giro ApplicationException, quindi è prevedibile che abbiano anticipato anche un cambiamento nelle raccomandazioni lungo la strada. (vedi http://blogs.msdn.com/b/kcwalina/archive/2006/06/23/644822.aspx )

Potrebbero esserci altri motivi (sto pensando che forse questo abbia a che fare con Reflection, o qualche altro motivo tecnico), quindi sto rendendo questo post un CW.


"Solo perché è" super ampio ", non è astratto." ... Ma questo è l'argomento dell'OP, non è vero. Non dovrebbe essere astratto, nel senso che qualche indicazione del tipo di eccezione deve sempre essere approvata.
Steven Jeuris,

Bene, aggiornerò la mia risposta di conseguenza - la natura di questa domanda è un po 'confusa perché "astratto" è sia una parola chiave del linguaggio sia il nome del concetto in discussione.
Kevin McCormick,

@KevinMcCormick: il termine "astratto" qui viene utilizzato come parola chiave della lingua. Per favore, dimmi come posso cambiare la mia domanda in modo che sia più chiara per i futuri lettori?
marco-fiset,

Penso che sia un'ottima domanda. Qualsiasi conversione OO relativa alla abstractparola chiave colpisce questo muro. Non sono sicuro di alcun modo per aggirarlo oltre a indicare la abstractparola chiave con i backtick.
Kevin McCormick,

2
In che modo "dissociare" una classe è un cambiamento decisivo?
configuratore
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.