| 

.NET C# Java Javascript Exception

4
Ich habe mich zwar damit abgefunden, dass es so ist. Weiss aber jemand ein einfache und logische Erklärung, wieso der nachfolgende Code sich nicht kompilieren lässt.
Im Prinzip wäre eine Liste von "Sportwagen" auch eine liste von "Fahrzeugen", oder?
Class Fahrzeug
End Class

Class Sportwagen
Inherits Fahrzeug
End Class

Class App
Sub test()
Dim aa As Fahrzeug
Dim bb As Sportwagen = New Sportwagen
aa = bb
' Das funktioniert und ist ja auch logisch'

Dim a As List(Of Fahrzeug)
Dim b = New List(Of Sportwagen)
a = b
' Das funktioniert nicht. Wieso denn?'
' System.Collections.Generic.List(Of Sportwagen) kann nicht in'
' System.Collections.Generic.List(Of Fahrzeug) konvertiert werden.'
' Verwenden Sie stattdessen'
' System.Collections.Generic.IEnumerable(Of Fahrzeug).'

End Sub
End Class
News:
17.03.2011
Fredo 495 8
4 Antworten
7
Ganz einfach: a und b sind unterschiedliche Typen. Die Vererbungsfolge für deine Sportwagenklasse ist:
Object => Fahrzeug => Sportwagen

Für die beiden Listen hingegen:
List => List(of Fahrzeug)
List => List(of Sportwagen)

Beide Listen haben zwar einen gemeinsamen Vorfahren, aber das war es auch schon. Sie sind nicht von einander abgeleitet.
17.03.2011
m.fuchs 1,6k 8
2
Für das Warum hat m.fuchs bereits eine Antwort gegeben. Vielleicht kann ich beim Wie dann helfen.
Hier könntest du die List<T>.ConvertAll<TOutput> Method verwenden.
17.03.2011
Jürgen Luhr 6,9k 1 8
1
Was gehen könnte ist:

Dim a As List(Of Fahrzeug)
Dim b = New List(Of Sportwagen)
a.AddRange(b.ToArray())
17.03.2011
Floyd 11,0k 3 9
1
Um das "warum" noch etwas zu vertiefen: stell Dir vor, Du reichst die Liste a an eine andere Methode weiter, die eine List<Of Fahrzeug> entgegennimmt. Und es gibt vielleicht auch noch LKWs. Die gerufene Methode sollte mit Fug und Recht erwarten können, dass sie in die Liste einen LKW einfügen darf. Wenn Du vorher aber b an a zugewiesen hast, ist es tatsächlich nur noch eine List<Of Sportwagen>, die keinen LKW aufnehmen kann. Es würde dann bei jemandem knallen, der gar nichts dafür kann. Deshalb ist das bis .NET 3.5 komplett unterbunden gewesen (für Generics, aber interessanterweise nicht für Arrays, nebenbei gesagt).

In .NET 4 gibt es neue Möglichkeiten, so etwas unter bestimmten Bedingungen zu erlauben. Für Details siehe die MSDN zu Ko- und Kontravarianz in .NET 4. Wenn ich es nicht gerade durcheinander bringe (kann es gerade nicht testen), müßte Dein Code in .NET 4 funktionieren, wenn a als IEnumerable<Fahrzeug> deklariert wird (denn mit IEnumerable kann das oben beschriebene Problem nicht auftreten, weil man einem IEnumerable nichts hinzufügen kann).
17.03.2011
Matthias Hlawatsch 8,4k 2 8
Ich glaub du hast da was falsch gelesen, wenn a = List(Of Fahrzeug) und b = List(Of Sportwagen) kann a = b nur List(Of Fahrzeug) sein und nicht List(Of Sportwagen). "string a = (double)1.1" ist ja auch vom Typ "string" und nicht "double". Immer der Linke Typ bleibt stehen.
Floyd 17.03.2011
@Floyd wenn ich

object a = "1234";

schreibe, ist a als object deklariert und verweist auf einen String. Ich kann dann mit a alles machen, was mit object geht.
Wenn in gleicher Weise

List<Fahrzeug> a = new List<Sportwagen>();

möglich wäre (und die Frage war ja, warum das nicht geht), würde a auf eine List<Sportwagen> verweisen, aber ich könnte damit alles machen, was mit List<Fahrzeug> geht, insbesondere Add(lkw). das wollte ich verdeutlichen.
(Sorry für die C#-Syntax, aber das kann ich schneller und sicherer).
Matthias Hlawatsch 17.03.2011
Sehr interessanter Link. Danke.
Fredo 17.03.2011
Falsch, da object und List<Fahrzeug> zwei föllig verschiedene Sachen sind. Du hast eine Liste vom Typ Fahrzeug und kein Variable vom object welche wie ein Variant funktioniert. Da Sportwagen von Fahrzeug abgeleitet ist, könnte in der Theorie a=b funktionieren und der Typ von a ändert sich nicht. Das geht nur bei dynamic und object Typen.
Floyd 17.03.2011
@Matthias: so erklärt, leuchtet es ein.
Kein Problem mit C#-Syntax.
Fredo 17.03.2011
Korrektur, "object a = "1234";" bleibt vom Typ object, verweißt nur auf einen String. Nur bei dynamic ändert sich der Variablentyp meines wissens nach (wobei ich nocht nicht viel mit dynamic gearbeitet habe)
Floyd 17.03.2011

Stelle deine .net-Frage jetzt!