InvalidCastException bei Generics?
-
Hi!
bei folgenden Code bekomme ich eine InvalidCastException:interface IView<T> where T:IGebaeck { T Ware { get; set; } } class AbstractView<T> : IView<T> where T: IGebaeck { private T t; ... } class BrezleView : AbstractView<Brezle> //Brezle ist von IGebaeck abgeleitet { ... } static class Baeckerei { public static IView<IGebaeck> createGebaeckView() { BrezleView brezle = new BrezleView(); return (IView<IGebaeck>)brezle; } }
Warum? Up-Casts müssten doch ohne weiteres gehen oder?!
Danke
-
IView<IGebaeck> ist kein Supertyp von BrezleView, da du in letzteres nur Brezeln einfügen darfst, in ersteres aber alle Arten von Gebäck. Du könntest also, wenn das ginge, plötzlich in deinem BrezleView einen Keks vorfinden, was du natürlich nicht erwarten würdest.
Das ist ein Standardbeispiel für eine Verletzung des Liskov Substitution Principles und kann auch einfacher durch Arrays demonstriert werden.
-
Bashar schrieb:
Das ist ein Standardbeispiel für eine Verletzung des Liskov Substitution Principles und kann auch einfacher durch Arrays demonstriert werden.
… wo es allerdings funktioniert (d.h., Arrays erlauben sowas). Leider ist in den .NET-Sprachen wohl nicht geplant, generische Kovarianz/Kontravarianz einzuführen, wie z.B. in Java, obwohl das Common Type System das explizit beherrscht.
-
Bei Arrays geht sowas? OK dann hab ich unzulässig von Java herüber gefolgert. Und wenn es da auch nicht geht, weiß ich auch nicht mehr
Was passiert denn, wenn ich ein Brezel[] nach Gebaeck[] caste und einen Keks einfüge?
-
Bashar schrieb:
Bei Arrays geht sowas? OK dann hab ich unzulässig von Java herüber gefolgert. Und wenn es da auch nicht geht, weiß ich auch nicht mehr
Was passiert denn, wenn ich ein Brezel[] nach Gebaeck[] caste und einen Keks einfüge?
Auch in Java ist das möglich, allerdings halt nicht in Verbindung mit Generics. Siehe z.B. http://java.sun.com/javase/6/docs/api/java/lang/ArrayStoreException.html
-
Bashar schrieb:
Bei Arrays geht sowas? OK dann hab ich unzulässig von Java herüber gefolgert.
Na, das geht auch in Java – das ist übrigens der Grund dafür, dass es in .NET geht: man wollte zu Java kompatibel bleiben:
class Test { public static void main(String[] args) { Integer[] numbers = {1, 2, 3, 4}; Object[] objs = numbers; } }
=>
$ javac Test.java -verbose … [wrote Test.class] [total 536ms] $
Was passiert denn, wenn ich ein Brezel[] nach Gebaeck[] caste und einen Keks einfüge?
Aufwendiger Laufzeittest: 'ArrayStoreException' in Java, 'ArrayTypeMismatchException' in .NET.
-
waldbesitzer schrieb:
Auch in Java ist das möglich, allerdings halt nicht in Verbindung mit Generics.
Eben gerade doch. Es *ist* in Java möglich, und sogar auch in .NET (Erlang.NET z.B.), nur eben nicht in C# oder VB.
import java.util.*; class Test { public static void main(String[] args) { List<? extends Object> objList = new ArrayList<String>(); } }
-
Ah OK, dann hab ich das verwechselt.