Entwickler-Ecke
Basistechnologien - Generic auf Basistyp casten?
shamanu - Do 06.05.10 19:16
Titel: Generic auf Basistyp casten?
Ich habe eine abstrakte Basisklasse:
C#-Quelltext
1:
| public class BasicClass ... |
Und mehrere die davon ableiten:
C#-Quelltext
1: 2: 3:
| public class ClassA:BasicClass ... public class ClassB:BasicClass ... public class ClassC:BasicClass ... |
usw.
Diese Klassen werden nun von einer generischen verwendet:
C#-Quelltext
1:
| public class GenericClass<T> where T:BasicClass |
jetzt erhalte ich die generische Klasse als objekt, würde dies jedoch gerne auf den generischen Typen casten:
C#-Quelltext
1: 2: 3:
| public void foo(object genericClass){ GenericClass<BasicClass> gen=genericClass as GenericClass<BasicClass>; } |
Das ganze funktioniert jedoch nicht da das objekt genericClass vom typ GenericClass<ClassA> oder GenericClass<ClassB> usw ist. Ist es möglich das casting auf den generischen basistyp irgendwie durchzuführen?
Xardas008 - Do 06.05.10 21:56
Hi,
einen Cast kannst du so ohne weiteres bei Generischen Typen nicht durchführen. Der Grund hierfür ist, das Generics die Vererbungsbeziehung aufheben, diese besteht nur ausserhalb der Generics. Es gibt aber einen Trick den du anwenden kannst. Anbei habe ich (allerdings in Java) einen kleinen Codeausschnitt als Beispiel, den ich eben in Netbeans ausprobiert habe, den solltest du ohne weiteres auf C# übertragen können.
C#-Quelltext
1: 2: 3: 4: 5:
| ArrayList<Base> b = new ArrayList<Base>(); ArrayList<Derived> d = new ArrayList<Derived>(); Derived d2 = d.get(0); b.add(d2); b.add(d); |
Und zwar ist der Trick, das du dir das zu castende Element aus ClassA nimmst und nach ClassA castest und dieses dann in die BasisClass hinzufügst als neues Element, dies wird dann implizit in den richtigen Typ gecastet.
Gruß
shamanu - Fr 07.05.10 23:06
Ok, das casting über ein Interface mit <out T> funktioniert soweit einmal.
Ich muß mir das ganze nochmals genauer anschauen und melde mich dann nochmals.
shamanu - Do 13.05.10 22:42
Ich habe die <out T> variante mit Interface nun getestet.
In der Basisversion funktioniert es, jedoch verwende ich in meinen Klassen einen Kontainer welcher einen fehler bezüglich 'T' erzeugt der sagt das der T parameter invariantly sein muß.
C#-Quelltext
1: 2: 3: 4:
| public interface IElementBase<out T> where T : SingleElementBase { IObservable<KeyValuePair<string, T>> Elements{get; set;} } |
Bezüglich der Frage ob dies wirklich notwendig ist bzw. der konkrete Fall:
Ich habe eine generische Basisklasse "ElementBase". Die konkreten Implementierungen halten dann Sammlungen von zb Audiofiles, Grafiken usw. und werden über einen Contentpresenter dargestellt.
Das hat alles soweit gut funktioniert. Jedoch erweitere ich das ganze nun um eine neue Gui und würde die Objekte gerne als Parameter übergeben ohne für jede Klasse die von ElementBase ableitet eine eigene Methode zu erstellen.
Kha - Do 13.05.10 23:35
In der Theorie ist an dem Code nichts auszusetzen, praktisch sträubt sich aber eben
KeyValuePair dagegen. Da wirst du auf ein eigenes
C#-Quelltext
1: 2: 3: 4: 5:
| interface ITuple<out T1, out T2> { public T1 Item1 { get; } public T2 Item2 { get; } } |
ausweichen müssen.
shamanu hat folgendes geschrieben : |
| Jedoch erweitere ich das ganze nun um eine neue Gui und würde die Objekte gerne als Parameter übergeben ohne für jede Klasse die von ElementBase ableitet eine eigene Methode zu erstellen. |
Auf GUI-Ebene (gerade wenn es um WPF geht) ist Typisierung meist nicht mehr wichtig. Wäre es nicht einfacher, eine nicht-generische
ElementBase-Basisklasse einzuschieben?
shamanu - Fr 14.05.10 21:55
Kha hat folgendes geschrieben : |
| Auf GUI-Ebene (gerade wenn es um WPF geht) ist Typisierung meist nicht mehr wichtig. Wäre es nicht einfacher, eine nicht-generische ElementBase-Basisklasse einzuschieben? |
Die ElementBase Klasse habe ich eigentlich primär generisch gemacht um einen großen Teil der funktionalität darin implementieren zu können und bei den Elementen die sie hält unabhängig von einem Interface oder ähnlichem zu sein.
Inzwischen scheint mir diese Lösung aber nicht mehr gerade als die Beste. Der Vorschlag mit ITuple funktioniert zwar aber wenn ich noch weiter Funktionalitäten benötige führt dies wohl schnell zu noch mehr Hilfskonstrukten.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!