Super typ wyjątku abstrakcyjnego

17

Jeśli rzucanie System.Exceptionjest uważane za tak złe, dlaczego nie zostało Exceptionwykonaneabstract ?

W ten sposób nie będzie możliwe wywołanie:

throw new Exception("Error occurred.");

Wymusiłoby to użycie wyjątków pochodnych, aby podać więcej szczegółów na temat błędu, który wystąpił.

Na przykład, gdy chcę podać niestandardową hierarchię wyjątków dla biblioteki, zwykle deklaruję abstrakcyjną klasę bazową dla moich wyjątków:

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

A potem kilka wyjątków pochodnych o bardziej szczegółowym celu:

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

Następnie podczas wywoływania dowolnej metody bibliotecznej można mieć ten ogólny blok try / catch, aby bezpośrednio wychwycić dowolny błąd pochodzący z biblioteki:

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

Czy to dobra praktyka?

Czy byłoby dobrze, gdyby Exceptionzostał streszczony?

EDYCJA: Chodzi mi o to, że nawet jeśli klasa wyjątku jest zaznaczona abstract, nadal możesz złapać ją w bloku catch-all. Uczynienie go abstrakcyjnym to tylko sposób, aby zabronić programistom zgłaszania wyjątku „super-szeroki”. Zwykle, kiedy dobrowolnie zgłaszasz wyjątek, powinieneś wiedzieć, jaki to typ i dlaczego tak się stało. Wymuszając w ten sposób wyrzucenie bardziej konkretnego typu wyjątku.

marco-fiset
źródło
3
+1 „Najlepszym sposobem zapobiegania nieprawidłowemu użyciu jest uniemożliwienie takiego użytkowania”. - Scott Meyers
Steven Jeuris
3
„Czy byłoby dobrze, gdyby wyjątek uczyniono abstrakcyjnym?” - Absolutnie nie, ponieważ cały istniejący kod .NET, który używa nowego wyjątku („...”), zostałby uszkodzony. Jednak „Czy zespół .NET powinien zacząć od wyjątku jako wyjątku?” - prawdopodobnie tak, ale teraz jest o 10 lat za późno :)
MattDavey

Odpowiedzi:

11

Nie znam rzeczywistych powodów, dla których tak się stało, i do pewnego stopnia zgadzam się, że zapobieganie rzucaniu nieskończenie szerokich wyjątków byłoby dobrą rzeczą.

ALE ... podczas kodowania małych aplikacji demonstracyjnych lub sprawdzania koncepcji, nie chcę zaczynać projektować 10 różnych podklas wyjątków ani spędzać czasu na podejmowaniu decyzji, która z nich jest „najlepszą” klasą wyjątków w danej sytuacji. Wolę po prostu rzucić Exceptioni podać ciąg, który wyjaśnia szczegóły. Kiedy nadszedł jednorazowe kod, nie dbam o tych rzeczach i gdybym został zmuszony do dbania o takich rzeczach, to bym albo stworzyć własną GenericExceptionklasę i rzucać , że wszędzie, albo przenieść się do innego narzędzia / języka. W przypadku niektórych projektów zgadzam się, że prawidłowe tworzenie odpowiednich podklas wyjątków jest ważne, ale nie wszystkie projekty tego wymagają.

FrustratedWithFormsDesigner
źródło
Całkowicie się z tobą zgadzam, ale pytanie domyślnie dotyczyło nietrywialnych projektów.
marco-fiset
3

Możliwość A: To logicznie poprawne.

Masz rację, że Microsoft wraz z wieloma innymi nie sugerują rzucania new Exception() bezpośrednio z wielu powodów.

Biorąc to pod uwagę, możemy uznać akademicki ideał, że celem Exceptionhierarchii klas jest zdefiniowanie efektu zwężenia, tak aby można było wychwycić tylko najbardziej specyficzne wyjątki. (tzn. ArgumentNullExceptionjest węższy niż ArgumentException).

Klasa Exception nie jest wyjątkiem (kalambur nie jest przeznaczony). Ma to być najszerszy możliwy wyjątek, „super wyjątek”, którego prawie nie można uchwycić, ponieważ jego zakres jest nieskończenie szeroki. „Wyjątek” nie jestabstract że wyjątek nie może istnieć jako całość sama w sobie. Nie może (choć wprawdzie nie określono jeszcze dobrych przypadków - patrz możliwość B), a zatem powinna być publicznie możliwa do zbudowania.

Słowo „abstrakcyjne” (w sensie czysto akademickim) ma zastosowanie tylko wtedy, gdy klasa podstawowa sama w sobie nie ma sensu - tj FourLeggedAnimal.

Wszystko to na uwadze, nie byłoby techniczny powód, aby zrobić klasę abstract, inna niż być źródłem pogorszenia deweloperom .

Możliwość B: Design Lock-in / Nie wiedzieli

Jeśli stwardnienie rozsiane uczyniło tę klasę abstrakcyjną, mogliby mieć kłopoty, gdyby zmienili zdanie na później, ponieważ klasa ta jest bardzo istotna dla podstaw języka. Oni już wygłupili się ApplicationException, więc można przewidzieć, że spodziewali się również zmiany rekomendacji na późniejszym etapie. (patrz http://blogs.msdn.com/b/kcwalina/archive/2006/06/23/644822.aspx )

Mogą istnieć inne powody (myślę, że może to ma związek z Reflection lub z innych przyczyn technicznych), dlatego wpisuję ten post w CW.

Kevin McCormick
źródło
„Tylko dlatego, że jest„ bardzo szeroki ”, nie jest abstrakcyjny.” ... Ale to nie jest argument OP. Czy nie powinno to być abstrakcyjne w tym sensie, że zawsze trzeba przekazać pewne wskazanie rodzaju wyjątku?
Steven Jeuris
Dobrze, odpowiednio zaktualizuję swoją odpowiedź - charakter tego pytania jest nieco mylący, ponieważ „streszczenie” jest zarówno słowem kluczowym języka, jak i nazwą omawianego pojęcia.
Kevin McCormick
@KevinMcCormick: Termin „streszczenie” jest tutaj używany jako słowo kluczowe języka. Powiedz mi, jak mogę zmienić swoje pytanie, aby było bardziej zrozumiałe dla przyszłych czytelników?
marco-fiset
Myślę, że to świetne pytanie. Wszelkie konwersje OO dotyczące abstractsłowa kluczowego trafiają w tę ścianę. Nie jestem pewien, jak można to obejść poza oznaczeniem abstractsłowa kluczowego za pomocą strzałek wstecznych.
Kevin McCormick
2
Jak „dezabstrakcja” klasy jest przełomową zmianą?
konfigurator