Hi!
Hab grad was erfunden: die generische Exception.
Damit hat man für jede Klasse, die man implementiert, eine spezifische Exception zur Verfügung, ohne Extra-Code schreiben zu müssen.
Und als Extension schreibt sich das Exception-Werfen auch sehr bequem.
namespace System {
//Extension-Methods für alle Klassen
public static class ObjectX {
public static Exception<T> Exception<T>(this T subj, params object[] msgSegments) {
return new Exception<T>(subj, msgSegments);
}
}
//generische Exception
public class Exception<T> : System.Exception {
/// <summary>
/// stellt den Fehler-Werfer fürs Debuggen zur Verfügung
/// </summary>
public readonly T Sender;
public Exception(T sender, params object[] msgSegments)
: base(sender.GetType().Name + "-Exception: " + string.Concat(msgSegments)) {
Sender = sender;
}
}
//Test-Klasse, die eine generische Exception wirft
public class CrashTest {
public void Test(int wrongArgument) {
throw this.Exception(wrongArgument, " is inappropriate!");
}
}
public class Program {
//testet typ-spezifisches catchen und natürlich, wie die Ausgabe aussieht
static void Main(string[] args) {
try {
var ct = new CrashTest();
ct.Test(42);
}
catch (Exception<CrashTest> x) {
// die generische Exception ermöglicht "von Natur aus" typ-spezifisches catchen
throw; //re-throwing, um die Ausgabe anzugucken
}
}
}
}
Der frühe Apfel fängt den Wurm.
Servus und Guten Morgen
Das ist eine schöne sache... kann man sicher nicht nur einmal oder wenig oft gebrauchen vielen dank 😄
Grüße
private int Main()
{
string programmingSkills = getMySkills("programming")
return = 1;
}
leite mal nicht direkt von Exception ab sondern nimm ApplicationException. Microsoft hält sich zwar selbst nicht an sein eigenes Schema Fehler zwischen Anwendung und System/CLR (SystemException) zu trennen, schaden sollte es aber nicht.
Den Fehlertext als params zu anzugeben find ich auch nicht unbedingt das wahre. Ein zusätzlich Nicht-params-Überladung wäre nicht schlecht, sowie einen (oder mehrere Konstruktoren) die auch innerException implementieren.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
leite mal nicht direkt von Exception ab sondern nimm ApplicationException.
das sollte man wirklich meiden, da die exceptiontabelle innerhalb der clr erst beim schmeißen der entsprechenden exception gebaut wird und hier hat die clr verbundene hände. daher haben die erstmal eingbeaut das er zwecks vererbung erstmal die klasse exception selbst sucht und wenn diese nciht passt (als basistyp) dann geht er alle typen der assembly durch um den passenden basistyp zu finden. das kann recht viel performance kosten beim erstmaligen schmeißen der exception.
Es gibt auch noch eine Guideline, dass man die ApplicationException nicht verwenden sollte, weil sie unnütz ist:
ApplicationException considered useless
Laut dem Post war sie dazu gedacht Exceptions aus der CLR von eigenen Exceptions unterscheiden zu können. Da die CLR aber teilweise Exceptions wirft die von ApplicationException abgeleitet sind, ist das Unterfangen sinnlos.
loop:
btst #6,$bfe001
bne.s loop
rts
Hllo kleines_eichhoernchen,
der von dir gegebene Rat entspricht der Empfehlung von Microsoft in .NET 1.0, wurde aber in .NET 2.0 revidiert:
Beachten Sie, dass "Abfangen und Auslösen von Standardausnahmetypen" eine Richtlinie enthält, die bestimmt, dass benutzerdefinierte Ausnahmen nicht von ApplicationException abgeleitet werden sollen. [Nämlich:]
Lösen Sie System.ApplicationException nicht aus, und leiten Sie die Ausnahme nicht ab.
Hallo ErfinderDesRades,
ich fürchte, dein Ansatz geht nicht konform mit dem Empfehlungen von Microsoft, denn:
Lösen Sie nach Möglichkeit die in den System-Namespaces vorhandenen Ausnahmen aus, statt benutzerdefinierte Ausnahmetypen zu erstellen.
herbivore
@kleines_eichhoernchen
Das mit den params
findich grad ziemlich komfortabel. Wie gezeigt, kannich beliebige Argumente mit Text gemischt hineinschmeißen, und er macht das ToString() intern.
Jetzt habichs so:
namespace System {
//Extension-Methods für alle Klassen
public static class ObjectX {
public static Exception<T> Exception<T>(
this T sender, object firstMsgSegment, params object[] msgSegments) {
return Exception<T>(sender, null, firstMsgSegment, string.Concat(msgSegments));
}
public static Exception<T> Exception<T>(
this T sender, Exception innerException, params object[] msgSegments) {
return new Exception<T>(sender, innerException, string.Concat(msgSegments));
}
public static Exception<T> Exception<T>(this T sender) {
return Exception<T>(sender, null);
}
}
/// <summary> generische Exception </summary>
public class Exception<T> : System.Exception {
/// <summary> stellt den Fehler-Werfer fürs Debuggen zur Verfügung </summary>
public readonly T Sender;
public Exception(T sender, Exception innerException, string message)
: base(string.Concat(
sender.GetType().Name,
"-Exception",
string.IsNullOrEmpty(message) ? "" : ": " + message),
innerException) {
Sender = sender;
}
}
//Test-Klasse, die eine generische Exception wirft
public class CrashTest {
public void Test(int wrongArgument) {
throw this.Exception(wrongArgument, " is inappropriate!");
}
}
public class Program {
//testet typ-spezifisches catchen und natürlich, wie die Ausgabe aussieht
static void Main(string[] args) {
try {
var ct = new CrashTest();
ct.Test(42);
}
catch (Exception<CrashTest> x) {
// die generische Exception ermöglicht "von Natur aus" typ-spezifisches catchen
throw; //re-throwing, um die Ausgabe anzugucken
}
}
}
}
Also eine generische Exception, die aber mit 3 Extension-Überladungen erzeugt werden kann:*einmal ohne alles *einmal mit beliebig vielen, beliebigen Argumenten - die werden zur Meldung verkettet *einmal mit InnerException + beliebigen Meldungs-Segmenten
Ah! - Zwischen posts -
Lösen Sie nach Möglichkeit die in den System-Namespaces vorhandenen Ausnahmen aus, statt benutzerdefinierte Ausnahmetypen zu erstellen.
Wieso hat TryCatch dann dieses Feature, dass der Catch-Block genau nach Exception-Typ differenzieren kann - wenn man dann doch nur Standard-Exceptions auslösen soll?
Das scheint mir doch sehr nützlich für eine differenzierte Fehlerbehandlung.
Die sind ja auch iwi lustig: Erst selbst hunderte von Exceptions erfinden, für alle möglichen Belange, und dann empfehlen, keine weiteren zu erfinden, für eigene Belange!
Vonne Intention her ist die generische Exception ja eigentlich gar nicht mal so konträr zur zitierten Empfehlung: Weil sie hilft ja, mit wenigen Exception-Typen auszukommen, und bietet trotzdem eine hohe Differenzierung.
Kann mir gut vorstellen, daß inne nächsten Version auchn paar generische Exceptions enthalten sind, vergleicbar mit dem generischen Eventhandler, der ja auch einen wahren Eventhandler-Delegaten-Dschungel aufräumt, oder den generischen Actions und Funcs, die ja im Grunde jeden Delegaten emulieren können.
Der frühe Apfel fängt den Wurm.
Wieso hat TryCatch dann dieses Feature, dass der Catch-Block genau nach Exception-Typ differenzieren kann - wenn man dann doch nur Standard-Exceptions auslösen soll?
Weil es ja auch verschiedene "Standard"-Exceptions gibt. Allerdings sind die nach Art des Fehlers gegliedert und nicht nach den auslösenden Objekten, z.B. ArgumentNull, OutOfRange, NotImplemented etc.
Wenn dein Objekt eine bestimmte neue Art von Fehlern erzeugt, baust du dir nach dem gleichen Schema eigene Exception-Klassen, wie es auch von Microsoft gemacht wird, z.B. DirectXException usw. usf.
Ich verstehe also nicht, wozu deine Klasse gut sein soll. Vielleicht willst du auch deinem Namen alle Ehre machen und das Rad neu erfinden...?
Schöne Grüße,
Christian
Weeks of programming can save you hours of planning
Hallo ErfinderDesRades,
Wieso hat TryCatch dann dieses Feature, dass der Catch-Block genau nach Exception-Typ differenzieren kann - wenn man dann doch nur Standard-Exceptions auslösen soll?
Das sollten wir bitte nicht hier bei den Snippets ausdiskutieren. Deshalb nur soviel: Die Aussagen von MS ist "benutzerdefinierte Ausnahmetypen nach **Möglichkeit **zu vermeiden". Wenn sich eine Differenzierung anbietet, wären eigene Exceptions also in Ordnung. Aber selbst dann sollte die Differenzierung nach der Art der Ausnahme erfolgen und sicher nicht nach der Klasse, die die Ausnahme wirft, wie das bei deinem Snippet der Fall ist.
Die sind ja auch iwi lustig: Erst selbst hunderte von Exceptions erfinden, für alle möglichen Belange, und dann empfehlen, keine weiteren zu erfinden, für eigene Belange!
Gerade weil es schon für soviele Belange Ausnahmen gibt, wird man kaum in die Situationen kommen, in denen man eigene Exceptions braucht. Daher ist die Empfehlung in meinen Augen voll gerechtfertigt und dein Snippet geht nun mal leider nicht konform damit.
herbivore