none
Zweisen einer Klasse zu einem Interface RRS feed

  • 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

    Mittwoch, 7. September 2011 10:36

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
    Mittwoch, 7. September 2011 12:20
  •  


    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


    Mittwoch, 7. September 2011 10:56
  • 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
    Mittwoch, 7. September 2011 11:30
  • 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:

                // oder via Konstruktor (ein Methodenaufruf)
                List<INodeViewViewModelBase> nodeViews = new List<INodeViewViewModelBase>(
                     root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)));
    
    
    was dem ersten Schnipsel am nächsten käme.
    Alternativ geht AddRange, das ebenso ein IEnumerable<T> akzeptiert.

    Gruß Elmar

    • Als Antwort markiert Pawel Warmuth Donnerstag, 8. September 2011 03:56
    Mittwoch, 7. September 2011 22:51
    Beantworter

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


    Mittwoch, 7. September 2011 10:56
  • 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
    Mittwoch, 7. September 2011 11:30
  • Hallo Ihr beide,

    ja das Casten habe ich bereits gemacht. Mich wunderte eben nur, dass in einer Schleife das zuwesien funktoniert und in einem LINQ Statement eben nicht.....

    Grüße

    Mittwoch, 7. September 2011 11:38
  • 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
    Mittwoch, 7. September 2011 11:57
  • Nein im Beispiel nicht, das habe ich danach gemacht ;-)

    Ich sehe aber immer ncoh keine Erklrärung warum ich in einer Schleife einer List<MeinInterface> die Klasse zuweisen kann ohne Casten , im Select aber nicht .....

    Grüße

    Mittwoch, 7. September 2011 12:03
  • 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
    Mittwoch, 7. September 2011 12:20
  • Hi Frank,

    da liegt der Hund begraben :-)

    Danke

     

    Mittwoch, 7. September 2011 12:40
  • 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:

                // oder via Konstruktor (ein Methodenaufruf)
                List<INodeViewViewModelBase> nodeViews = new List<INodeViewViewModelBase>(
                     root.SubNodes.Select(node => new SubNodeCheckboxModelViewModel(node, this)));
    
    
    was dem ersten Schnipsel am nächsten käme.
    Alternativ geht AddRange, das ebenso ein IEnumerable<T> akzeptiert.

    Gruß Elmar

    • Als Antwort markiert Pawel Warmuth Donnerstag, 8. September 2011 03:56
    Mittwoch, 7. September 2011 22:51
    Beantworter