Ich schreibe gerade Code für UnconstrainedMelody, der generische Methoden für Aufzählungen enthält.
Jetzt habe ich eine statische Klasse mit einer Reihe von Methoden, die nur für "Flags" -Aufzählungen verwendet werden sollen. Ich kann dies nicht als Einschränkung hinzufügen ... daher ist es möglich, dass sie auch mit anderen Aufzählungstypen aufgerufen werden. In diesem Fall würde ich gerne eine Ausnahme auslösen, bin mir aber nicht sicher, welche ich auslösen soll.
Nur um dies konkret zu machen, wenn ich so etwas habe:
// Returns a value with all bits set by any values
public static T GetBitMask<T>() where T : struct, IEnumConstraint
{
if (!IsFlags<T>()) // This method doesn't throw
{
throw new ???
}
// Normal work here
}
Was ist die beste Ausnahme zu werfen? ArgumentException
klingt logisch, aber es ist eine Art eher Argument als ein normales Argument, das könnte leicht verwirren Dinge. Soll ich meine eigene TypeArgumentException
Klasse vorstellen ? Verwenden InvalidOperationException
? NotSupportedException
? Noch etwas?
Ich würde lieber keine eigene Ausnahme dafür erstellen, es sei denn, es ist eindeutig das Richtige.
Antworten:
NotSupportedException
klingt so, als würde es eindeutig passen, aber die Dokumentation besagt eindeutig, dass es für einen anderen Zweck verwendet werden sollte. Aus der MSDN-Klasse Anmerkungen:Natürlich gibt es eine Art und Weise, die
NotSupportedException
offensichtlich gut genug ist, insbesondere angesichts ihrer Bedeutung für den gesunden Menschenverstand. Trotzdem bin ich mir nicht sicher, ob es genau richtig ist.Angesichts des Zwecks der unbeschränkten Melodie ...
... es scheint, als wäre ein neues
Exception
in Ordnung, trotz der hohen Beweislast, die wir zu Recht erfüllen müssen, bevor wir einen Brauch erstellenExceptions
. So etwasInvalidTypeParameterException
könnte in der gesamten Bibliothek nützlich sein (oder auch nicht - dies ist sicherlich ein Randfall, oder?).Müssen Kunden in der Lage sein, dies von BCL-Ausnahmen zu unterscheiden? Wann könnte ein Kunde dies versehentlich mit einer Vanille aufrufen
enum
? Wie würden Sie die Fragen beantworten, die sich aus der akzeptierten Antwort auf Welche Faktoren sollten beim Schreiben einer benutzerdefinierten Ausnahmeklasse berücksichtigt werden?quelle
InvalidOperationException
sind eklig, weil "Foo die Sammlungsleiste auffordert, etwas hinzuzufügen, das bereits vorhanden ist, also wirft Bar IOE" und "Foo die Sammlungsleiste auffordert, etwas hinzuzufügen, also ruft Bar Boz an, der IOE wirft, obwohl Bar dies nicht erwartet". werden beide den gleichen Ausnahmetyp auslösen; Code, der erwartet, den ersten zu fangen, erwartet den letzteren nicht. Das wurde gesagt ...Foo<T>
als "allgemeinen Typ" undFoo<Bar>
in diesem Zusammenhang als "spezifischen Typ" betrachten, obwohl zwischen ihnen keine "Vererbungs" -Beziehung besteht.Ich würde NotSupportedException vermeiden. Diese Ausnahme wird in dem Framework verwendet, in dem eine Methode nicht implementiert ist und eine Eigenschaft angibt, dass diese Art von Operation nicht unterstützt wird. Es passt hier nicht
Ich denke, InvalidOperationException ist die am besten geeignete Ausnahme, die Sie hier auslösen können.
quelle
T
eine mitenum
dekoriert istFlags
, wäre es gültig, NSE zu werfen.StupidClrException
macht einen lustigen Namen;)Generische Programmierung sollte zur Laufzeit keine ungültigen Typparameter auslösen. Es sollte nicht kompiliert werden, Sie sollten eine Durchsetzung der Kompilierungszeit haben. Ich weiß nicht, was es
IsFlag<T>()
enthält, aber vielleicht können Sie daraus eine Durchsetzung der Kompilierungszeit machen, z. B. den Versuch, einen Typ zu erstellen, der nur mit 'Flags' erstellt werden kann. Vielleicht kann einetraits
Klasse helfen.Aktualisieren
Wenn Sie werfen müssen , würde ich für InvalidOperationException stimmen. Der Grund dafür ist, dass generische Typen Parameter haben und Fehler in Bezug auf (Methoden-) Parameter um die ArgumentException-Hierarchie zentriert sind. Die Empfehlung zu ArgumentException besagt jedoch, dass
Es gibt mindestens einen Vertrauenssprung darin, dass Empfehlungen für Methodenparameter auch auf generische Parameter angewendet werden sollen, aber es gibt nichts Besseres in der SystemException-Hierarchie imho.
quelle
IsFlag<T>
Legt fest, ob die Aufzählung darauf[FlagsAttribute]
angewendet wurde und die CLR keine auf Attributen basierenden Einschränkungen aufweist. Es würde in einer perfekten Welt - oder es würde einen anderen Weg geben, es einzuschränken - aber in diesem Fall funktioniert es einfach nicht :(Ich würde NotSupportedException verwenden, da dies das ist, was Sie sagen. Andere als die spezifischen Aufzählungen werden nicht unterstützt . Dies würde natürlich in der Ausnahmemeldung deutlicher angegeben.
quelle
Ich würde mitgehen
NotSupportedException
. WährendArgumentException
sieht gut aus , es ist wirklich erwartet , wenn ein Argument an eine Methode übergeben nicht akzeptabel ist. Ein Typargument ist ein definierendes Merkmal für die tatsächliche Methode, die Sie aufrufen möchten, kein echtes "Argument".InvalidOperationException
sollte ausgelöst werden, wenn die von Ihnen ausgeführte Operation in einigen Fällen gültig sein kann, aber für die jeweilige Situation nicht akzeptabel ist.NotSupportedException
wird ausgelöst, wenn eine Operation von Natur aus nicht unterstützt wird. Zum Beispiel bei der Implementierung einer Schnittstelle, bei der ein bestimmtes Mitglied für eine Klasse keinen Sinn ergibt. Dies sieht nach einer ähnlichen Situation aus.quelle
Anscheinend verwendet Microsoft
ArgumentException
dafür, wie am Beispiel von Expression.Lambda <> , Enum.TryParse <> oder Marshal.GetDelegateForFunctionPointer <> im Abschnitt Ausnahmen gezeigt. Ich konnte auch kein anderes Beispiel finden (obwohl ich in der lokalen Referenzquelle nachTDelegate
und gesucht habeTEnum
).Ich denke also, es ist sicher anzunehmen, dass es zumindest in Microsoft-Code eine gängige Praxis ist,
ArgumentException
ungültige generische Typargumente neben einfachen variablen Argumenten zu verwenden. Da die Ausnahmebeschreibung in Dokumenten nicht zwischen diesen unterscheidet, ist sie auch nicht allzu langwierig.Hoffentlich entscheidet es ein für alle Mal über die Frage.
quelle
TypeArgumentException
ausArgumentException
, nur weil eine Art Argument ist keine reguläre Streit.Ich würde mit NotSupportedExpcetion gehen.
quelle
Das Auslösen einer benutzerdefinierten Ausnahme sollte immer dann erfolgen, wenn dies fraglich ist. Eine benutzerdefinierte Ausnahme funktioniert immer, unabhängig von den Anforderungen der API-Benutzer. Der Entwickler könnte beide Ausnahmetypen abfangen, wenn es ihn nicht interessiert, aber wenn der Entwickler eine spezielle Behandlung benötigt, ist er SOL.
quelle
Wie wäre es mit dem Erben von NotSupportedException? Obwohl ich @Mehrdad zustimme, dass es am sinnvollsten ist, höre ich Ihren Standpunkt, dass es nicht perfekt zu passen scheint. Erben Sie also von NotSupportedException, und auf diese Weise können Personen, die gegen Ihre API codieren, weiterhin eine NotSupportedException abfangen.
quelle
Ich bin immer vorsichtig, wenn ich benutzerdefinierte Ausnahmen schreibe, nur weil sie nicht immer klar dokumentiert sind und Verwirrung stiften, wenn sie nicht richtig benannt werden.
In diesem Fall würde ich eine ArgumentException für den Fehler der Flagsprüfung auslösen. Es hängt alles von den Vorlieben ab. Einige Codierungsstandards, die ich gesehen habe, gehen so weit, zu definieren, welche Arten von Ausnahmen in solchen Szenarien ausgelöst werden sollen.
Wenn der Benutzer versuchen würde, etwas zu übergeben, das keine Aufzählung ist, würde ich eine InvalidOperationException auslösen.
Bearbeiten:
Die anderen sprechen einen interessanten Punkt an, der nicht unterstützt wird. Meine einzige Sorge bei einer NotSupportedException ist, dass dies im Allgemeinen die Ausnahmen sind, die ausgelöst werden, wenn "dunkle Materie" in das System eingeführt wurde, oder anders ausgedrückt: "Diese Methode muss auf dieser Schnittstelle in das System eingegeben werden, aber wir haben gewonnen." erst in Version 2.4 einschalten "
Ich habe auch gesehen, dass NotSupportedExceptions als Lizenzausnahme ausgelöst werden. "Sie führen die kostenlose Version dieser Software aus, diese Funktion wird nicht unterstützt."
Bearbeiten 2:
Ein weiterer möglicher:
Die Ausnahme, die ausgelöst wird, wenn ungültige Argumente verwendet werden, die Enumeratoren sind.
quelle
LicensingException
Klasse werfen, von der sie erbenInvalidOperationException
.Ich würde auch für InvalidOperationException stimmen. Ich habe ein (unvollständiges) Flussdiagramm zu Richtlinien für das Auslösen von .NET-Ausnahmen erstellt, die auf den Framework Design Guidelines 2nd Ed basieren . vor einiger Zeit, wenn jemand interessiert ist.
quelle