Autor |
Beitrag |
FrEEzE2046
      
Beiträge: 109
Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
|
Verfasst: Di 18.05.10 21:29
Hallo,
ich habe zwei Exception Klassen, welche ich als generic type für FaultException benutze. Beide Klassen haben ein string-Member Message und eine unterschiedliche enum mit dem Namen ErrorCode. Besteht die Möglichkeit eine entsprechende FaultException Variable zunächst abstrakt zu deklarieren und den genauen Typen erst durch Zuweisung zu bestimmen? Letztendlich sollen die Message und der ErrorCode (als string) in die Datei geschrieben werden und da die Behandlung für beide Typen gleicehn ist, würde ich mir gerne Redundanz ersparen. Ich habe mir das ungefähr so gedacht:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
| [DataContract] public enum Exception1ErrorCode { None = 0, [EnumMember] First = 1, [EnumMember] Second = 2 }
[DataContract] public class Exception1 { [DataMember] string Message; [DataMember] Exception1ErrorCode ErrorCode; }
[DataContract] public enum Exception2ErrorCode { None = 0, [EnumMember] First = 1, [EnumMember] Second = 2 }
[DataContract] public class Exception2 { [DataMember] string Message; [DataMember] Exception2ErrorCode ErrorCode; }
public void Method() { object faultException; if( true ) { faultException = new FaultException<Exception1> ( new Exception1 { Message = "", ErrorCode = Exception1ErrorCode.First } ); } else { faultException = new FaultException<Exception2> ( new Exception2 { Message = "", ErrorCode = Exception2ErrorCode.First } ); } using (StreamWriter sw = new StreamWriter("")) { sw.WriteLine(faultException.Detail.Message + '\t' + faultException.Detail.ErrorCode.ToString()); } } |
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Di 18.05.10 23:15
Die Generics spielen hier erst einmal gar keine Rolle  . Wenn du auf gleichnamige Member verschiedener Klassen zugreifen willst, brauchst du eine gemeinsame Basisklasse oder Interface - alles andere wäre Duck Typing (also in C# entweder Reflection oder doch eine if-Reihe). Aber warum nicht einfach bei beiden Typen ToString entsprechend überschreiben?
_________________ >λ=
|
|
FrEEzE2046 
      
Beiträge: 109
Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
|
Verfasst: Mi 19.05.10 11:15
Eine gemeinsame Basisklasse macht aus zwei Gründen keinen Sinn:
1. Es sind DataMember, dieses Attribut würde nicht veerbt.
2. Nur Message ist ein gemeinsamer Typ (string).
C#-Quelltext 1:
| object o = Activator.CreateInstance(typeof(FaultException<>).MakeGenericType(typeof(ExceptionClass1))); |
So würde ich prinzipiell zumindest ein Objekt erstellen können, was aber dann wieder vom Typ object ist und ich müsste wieder mit "is" prüfen. Gibt es da wirklich keinen anderen Weg?
Da funktionieren die C++ Templates doch einfacher. Ich suche ungefähr so etwas in C#:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55:
| #include <iostream>
using std::cout; using std::string;
enum Exception1EnumCode { EXC1_None = 0, EXC1_First = 1, EXC1_Second = 2 }; enum Exception2EnumCode { EXC2_None = 0, EXC2_First = 1, EXC2_Second = 2 };
template<typename EnumType> struct Exception { string Message; EnumType ErrorCode; };
typedef struct Exception<Exception1EnumCode> Exception1; typedef struct Exception<Exception2EnumCode> Exception2;
template<class T> class GenericClass { public: T* data; };
template<class T> void print_generic_class(GenericClass<T>& gc) { cout << gc.data->Message.c_str() << '\t' << gc.data->ErrorCode << '\n'; }
int main() { GenericClass<Exception1> gc1 = {new Exception1()}; GenericClass<Exception2> gc2 = {new Exception2()};
gc1.data->ErrorCode = EXC1_First; gc1.data->Message = "Exception1";
gc2.data->ErrorCode = EXC2_Second; gc2.data->Message = "Exception2"; print_generic_class(gc1); print_generic_class(gc2);
delete gc1.data; delete gc2.data;
return 0; } |
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 19.05.10 12:50
Ich favorisiere immer noch ToString, aber ich gehe einfach mal davon aus, dass es dir auch ums Prinzip geht  .
FrEEzE2046 hat folgendes geschrieben : | 1. Es sind DataMember, dieses Attribut würde nicht veerbt. | Inherited = false spielt keine Rolle, solange du die Property nicht überschreibst  .
FrEEzE2046 hat folgendes geschrieben : | 2. Nur Message ist ein gemeinsamer Typ (string). |
Wenn du bestehenden Code nicht ändern kannst, kannst du immer noch welchen hinzufügen.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| public abstract class ExceptionBase { [DataMember] string Message;
abstract string ErrorCodeAsString { get; } }
[DataContract] public class Exception1 : ExceptionBase { [DataMember] Exception1ErrorCode ErrorCode;
override string ErrorCodeAsString { get { return ErrorCode.ToString(); } } }
... |
FrEEzE2046 hat folgendes geschrieben : | Da funktionieren die C++ Templates doch einfacher. |
Templates werden zur Kompilierzeit ersetzt, Generics sind ein Runtime-Feature der CLR. Mit Ersterem bekommst du Duck Typing und kryptische Fehlermeldungen frei Haus, mit Letzterem keins von beidem.
_________________ >λ=
|
|
FrEEzE2046 
      
Beiträge: 109
Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
|
Verfasst: Mi 19.05.10 13:00
So werde ich es dann wohl auch noch machen. Mir bringt es überhaupt nichts über Type zwar eine Instanz dieser Klasser zu erstellen, aber das Objekt dann nicht entsprechend verwenden zu können.
Ich kann also davon ausgehen, dass es keine solche Möglichkeit in C# gibt?
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 19.05.10 13:42
Du kannst davon ausgehen, dass keine einzige stark typisierte Sprache Duck Typing zur Laufzeit kennt. Und meiner Meinung nach braucht es das auch nicht zur Compile Time, da kann ich ja gleich Python einsetzen  .
_________________ >λ=
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mi 19.05.10 14:01
Ich werf mal das Stichwort " dynamic" in die Runde. Gleichzeitig rate ich aber von der Verwendung ab und schließe mich Kha an das man das nicht braucht bzw. nicht verwenden sollte.
|
|
FrEEzE2046 
      
Beiträge: 109
Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
|
Verfasst: Mi 19.05.10 16:30
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 19.05.10 17:13
Ralf Jansen hat folgendes geschrieben : | Ich werf mal das Stichwort "dynamic" in die Runde. |
Ich habe lieber auf Reflection verwiesen, damit grausiges Design auch entsprechend mit grausigem Code markiert ist  .
FrEEzE2046 hat folgendes geschrieben : | Dennoch habe ich mir auch "dynamic" angeschaut und es jetzt so gelöst: |
In deinem Code benutzt du überhaupt kein Feature von dynamic, da könnte genauso gut object stehen.
_________________ >λ=
|
|
FrEEzE2046 
      
Beiträge: 109
Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
|
Verfasst: Do 20.05.10 11:36
Kha hat folgendes geschrieben : | In deinem Code benutzt du überhaupt kein Feature von dynamic, da könnte genauso gut object stehen. |
Ja, da hast du natürlich recht. Ich habe aber doch gesagt, dass ich immer auf Message u. ErrorCode zugreifen muss und das ist dann schon ein Feature von dynamic, was ich nutze.
Den Code oben, hab ich schnell in einem Konsolenprogramm erstellt.
|
|
|