Benutzer mit den meisten Antworten
Zweisen einer Klasse zu einem Interface

Frage
-
Hallo zusammen, bisher dachte ich ich wusste alles rund um Interfaces :
Ich habe ein Interface INodeViewViewModelBase
Zwei Klassen : SubNodeModelViewModel : INodeViewViewModelBase
und SubNodeCheckboxModelViewModel : INodeViewViewModelBase
So und nun : Dieses klappt !
List<INodeViewViewModelBase> nodeViews = new List<INodeViewViewModelBase>(); foreach (Node node in root.SubNodes) { var model = new SubNodeChecbkoxModelViewModel(node, this); nodeViews.Add(model); }
Dieses nicht !List<INodeViewViewModelBase> nodeViews = root.SubNodes.Select(node => new SubNodeChecbkoxModelViewModel(node, this)).ToList();
Eigtl. ist es doch die selbe Anweisung ?Es grüßt ein Ratloser Pawel
Antworten
-
Hallo Pawel,
- Ich sehe aber immer noch keine Erklrärung warum ich in einer Schleife einer List<MeinInterface> die Klasse zuweisen kann ohne Casten , im Select aber nicht .....
nein, Du weist eben nicht List<MeinInterface> einer List<MeineKlasse>, sondern eine Instanz von MeineKlasse auf MeinInterface:
var model = new SubNodeChecbkoxModelViewModel(node, this);
Siehe dazu auch Kontravarianz:[Kovarianz und Kontravarianz]
http://msdn.microsoft.com/de-de/library/ee207183.aspx
http://www.dotnetpro.de/articles/downloadpdf.ashx?id=3447
ciao Frank- Als Antwort markiert Pawel Warmuth Mittwoch, 7. September 2011 12:39
-
Hallo Pawel,versuch mal folgendes:
List<INodeViewViewModelBase> nodeViews = root.SubNodes.Select(node => new SubNodeChecbkoxModelViewModel(node, this)).Cast<INodeViewViewModelBase>().ToList();
Hinzugekommen ist ".Cast<INodeViewViewModelBase>()".
Gruß,
Philip
- Bearbeitet Philip Proplesch Mittwoch, 7. September 2011 10:57
- Als Antwort markiert Pawel Warmuth Mittwoch, 7. September 2011 11:37
-
Hallo Pawel,
Am effektivsten benutzt Du im zweiten Fall:
ToList<INodeViewViewModelBase>()
anstatt ToList().
Ansonsten wäre auch eine implizite Umwandlung denkbar:[implicit (C#-Referenz)]
http://msdn.microsoft.com/de-de/library/z5z9kes2.aspx
ciao Frank- Als Antwort markiert Pawel Warmuth Mittwoch, 7. September 2011 11:37
-
Hallo Pawel,
um den armen Hund vollständig zu verbuddeln:
Bei einer Zuweisung (=) gelten die Regeln für den Zuweisungsoperator.
Bei einem Methodenaufruf die Regeln für die implizite Parameter-Konvertierung.Dein Linq nimmt eine Zuweisung vor und da weiß die rechte Seite vorher nicht,
was sie der der linken zuweisen soll. Ergo kann dort nicht vorab konvertiert werden.
Und eine List<Klasse> ist nicht zuweisungskompatibel zu einer List<Interface der Klasse>.Also entweder Du lieferst das gewünschte (hier ein Interface):
// List<INodeViewViewModelBase> var nodeViews = root.SubNodes.Select(node => (INodeViewViewModelBase)new SubNodeCheckboxModelViewModel(node, this)).ToList(); var nodeViews = root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)).ToList<INodeViewViewModelBase>(); var nodeViews = root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)).Cast<INodeViewViewModelBase>().ToList();
Wobei (in absteigender Präferenz) jeweils ein kompatibler Typ (hier List<Interface>) erzeugt wird.
Oder aber Du verwendest einen Methodenaufruf,
den List<T> vorausschauend bereits als Konstruktor via IEnumerable<T> bereitstellt:was dem ersten Schnipsel am nächsten käme.// oder via Konstruktor (ein Methodenaufruf) List<INodeViewViewModelBase> nodeViews = new List<INodeViewViewModelBase>( root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)));
Alternativ geht AddRange, das ebenso ein IEnumerable<T> akzeptiert.Gruß Elmar
- Als Antwort markiert Pawel Warmuth Donnerstag, 8. September 2011 03:56
Alle Antworten
-
Hallo Pawel,versuch mal folgendes:
List<INodeViewViewModelBase> nodeViews = root.SubNodes.Select(node => new SubNodeChecbkoxModelViewModel(node, this)).Cast<INodeViewViewModelBase>().ToList();
Hinzugekommen ist ".Cast<INodeViewViewModelBase>()".
Gruß,
Philip
- Bearbeitet Philip Proplesch Mittwoch, 7. September 2011 10:57
- Als Antwort markiert Pawel Warmuth Mittwoch, 7. September 2011 11:37
-
Hallo Pawel,
Am effektivsten benutzt Du im zweiten Fall:
ToList<INodeViewViewModelBase>()
anstatt ToList().
Ansonsten wäre auch eine implizite Umwandlung denkbar:[implicit (C#-Referenz)]
http://msdn.microsoft.com/de-de/library/z5z9kes2.aspx
ciao Frank- Als Antwort markiert Pawel Warmuth Mittwoch, 7. September 2011 11:37
-
Hallo Pawel,
-
... das Casten habe ich bereits gemacht. ...
in Deinem Code ja nicht.
List<SubNodeCheckboxModelViewModel> ist etwas anderes als:
List<INodeViewViewModelBase>, auch, wenn es davon abgeleitet ist.
BTW: Vielleicht reicht Dir ja im LINQ-Beispiel auch: var nodeViews = ...
auch, wenn der Typ dann eben List<SubNodeCheckboxModelViewModel> ist.
ciao Frank -
-
Hallo Pawel,
- Ich sehe aber immer noch keine Erklrärung warum ich in einer Schleife einer List<MeinInterface> die Klasse zuweisen kann ohne Casten , im Select aber nicht .....
nein, Du weist eben nicht List<MeinInterface> einer List<MeineKlasse>, sondern eine Instanz von MeineKlasse auf MeinInterface:
var model = new SubNodeChecbkoxModelViewModel(node, this);
Siehe dazu auch Kontravarianz:[Kovarianz und Kontravarianz]
http://msdn.microsoft.com/de-de/library/ee207183.aspx
http://www.dotnetpro.de/articles/downloadpdf.ashx?id=3447
ciao Frank- Als Antwort markiert Pawel Warmuth Mittwoch, 7. September 2011 12:39
-
Hallo Pawel,
um den armen Hund vollständig zu verbuddeln:
Bei einer Zuweisung (=) gelten die Regeln für den Zuweisungsoperator.
Bei einem Methodenaufruf die Regeln für die implizite Parameter-Konvertierung.Dein Linq nimmt eine Zuweisung vor und da weiß die rechte Seite vorher nicht,
was sie der der linken zuweisen soll. Ergo kann dort nicht vorab konvertiert werden.
Und eine List<Klasse> ist nicht zuweisungskompatibel zu einer List<Interface der Klasse>.Also entweder Du lieferst das gewünschte (hier ein Interface):
// List<INodeViewViewModelBase> var nodeViews = root.SubNodes.Select(node => (INodeViewViewModelBase)new SubNodeCheckboxModelViewModel(node, this)).ToList(); var nodeViews = root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)).ToList<INodeViewViewModelBase>(); var nodeViews = root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)).Cast<INodeViewViewModelBase>().ToList();
Wobei (in absteigender Präferenz) jeweils ein kompatibler Typ (hier List<Interface>) erzeugt wird.
Oder aber Du verwendest einen Methodenaufruf,
den List<T> vorausschauend bereits als Konstruktor via IEnumerable<T> bereitstellt:was dem ersten Schnipsel am nächsten käme.// oder via Konstruktor (ein Methodenaufruf) List<INodeViewViewModelBase> nodeViews = new List<INodeViewViewModelBase>( root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)));
Alternativ geht AddRange, das ebenso ein IEnumerable<T> akzeptiert.Gruß Elmar
- Als Antwort markiert Pawel Warmuth Donnerstag, 8. September 2011 03:56