2009-03-26 7 views
19

Ich würde sicher sein, dass diese Frage etwas anspricht, das in einer vorherigen Frage aufgeworfen worden wäre, aber ich konnte es nicht finden.Konvertieren einer Liste von Basistyp in eine Liste von vererbten Typ

Es gibt eine Methode in einer C# -Klasse, die als Parameter eine generische Liste einer Basisklasse verwendet. Ich muss eine Liste einer geerbten Klasse übergeben und weiß nicht genau, wie das geht. Ich bekomme einen Fehler bei meinen Versuchen. Unten ist ein Beispielcode, um dies zu illustrieren:

public class A 
{ 
    public static void MethodC(List<A>) 
    { 
     // Do Something here with the list 
    } 
} 
public Class B : A 
{ 
    // B inherits from A, A is the Base Class 
} 

// Code utilizing the above method 
List<B> listOfB = new List<B>(); 
A.MethodC((List<A>) listOfB); // Error: this does not work 
A.MethodC(listOfB.ToList<typeof(A)>()); // Error: this does not work 
A.MethodC(listOfB.ConvertAll<A>(typeof(A))); // Error: this does not work 
// how can I accomplish this? It should be possible I would think 

Hinweis: Hier ist meine letzte Arbeitsmethode als Referenz. Ich habe eine noch bessere Lösung für mein Problem gefunden, aber technisch gesehen war es keine Antwort auf die Frage, da meine Frage improvisiert formuliert wurde.

public static DataTable 
    ObjectCollectionToDataTable<GLIST> 
     (List<GLIST> ObjectCollection) where GLIST 
       : BaseBusinessObject 
     { 
      DataTable ret = null; 

      if (ObjectCollection != null) 
      { 
       foreach (var b in ObjectCollection) 
       { 

        DataTable dt = b.ToDataTable(); 
        if (ret == null) 
         ret = dt.Clone(); 
        if (dt.Rows.Count > 0) 
         ret.Rows.Add(dt.Rows[0].ItemArray); 
       } 
      } 

      return ret; 
     } 
+0

Das ist die gleiche Antwort, die ich Ihnen gab ... –

+0

Und es ist technisch die Antwort auf das, was Sie ursprünglich gefragt, auch! :) –

Antwort

29

Wenn Sie zur Verfügung Linq haben, können Sie tun

var ListOfA = ListOfB.Cast<A>().ToList(); 
+0

Ich glaube nicht, dass ich Linq habe, aber es hat trotzdem funktioniert. Vielen Dank für Ihre schnelle Antwort. – stephenbayer

+0

Mögliches Problem - muss MethodC die Liste ändern, sodass diese Änderungen außerhalb von MethodC sichtbar sind? –

+0

Froh, es hat funktioniert!Der einzige Grund, warum ich glaube, dass Sie die LINQ-Erweiterungsmethoden zur Verfügung haben, war die Verwendung von ToList in Ihrem Beispiel. –

9

Sie nicht das tun kann. Um zu verstehen, warum dies nicht erlaubt ist, stellen Sie sich vor, was passieren würde, wenn Add auf einem List<Derived> aufgerufen würde, nachdem es in eine List<Base> umgewandelt wurde.

Auch die Antworten, die darauf hinweisen, dass C# 4.0 anders sein wird, sind falsch. Liste wird nie geändert, um Ihnen dies zu ermöglichen. Nur IEnumerable wird - weil es nicht erlaubt, dass Elemente zur Sammlung hinzugefügt werden.

Update: Der Grund, warum es in der Lösung, für die Sie gegangen sind, funktioniert, ist, weil Sie nicht mehr die gleiche Liste übergeben. Sie erstellen eine ganz neue Liste, die eine Kopie des Originals ist. Deshalb habe ich nach einer Änderung der Liste gefragt; Wenn MethodC Änderungen an der Anzahl der Elemente in der Liste vornimmt, werden diese Änderungen an einer Kopie vorgenommen, nicht an der ursprünglichen Liste.

Ich denke, die ideale Lösung für Sie ist wie folgt:

public abstract class A 
{ 
    public void MethodC<TItem>(List<TItem> list) where TItem : A 
    { 
     foreach (var item in list) 
      item.CanBeCalled(); 
    } 

    public abstract void CanBeCalled(); 
} 

public class B : A 
{ 
    public override void CanBeCalled() 
    { 
     Console.WriteLine("Calling into B"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<B> listOfB = new List<B>(); 

     A a = new B(); 

     a.MethodC(listOfB); 
    } 
} 

Beachten Sie, wie mit dieser Lösung, Sie darauf, dass seltsame Umwandlung zu tun zuerst eine List<B> direkt an MethodC, ohne passieren kann. Also kein unnötiges Kopieren.

Der Grund, warum dies funktioniert, ist, weil wir MethodC gesagt haben, um eine Liste von allem zu akzeptieren, das von A abgeleitet ist, anstatt darauf zu bestehen, dass es eine Liste von A sein muss.

+0

Ich glaube nicht, dass das stimmt, es funktioniert gut. Mein Methodenaufruf arbeitet Schleifen durch die Sammlung und wirkt auf abstrakte Methoden und Eigenschaften. Ich habe den Code oben in einer früheren Antwort verwendet, und es funktioniert großartig. Das Projekt ist .NET 2.0 mit CSC.exe (C#) 3.0 als Compiler. – stephenbayer

+0

Siehe Update oben. –

+0

Ich schätze, Sie haben Schwierigkeiten, dies zu arbeiten? :) –

3

Hier ist eine Antwort, die alle Objekte in Ihrer Liste des falschen Typs ausschließt. Dies ist eine viel sicherere Art und Weise meiner Meinung nach:

List<A> ListOfA = ListOfB.OfType<A>().ToList(); 

Die OfType Methode Posten der falschen abgeleiteten Klasse ausschließen, wo als die Cast wird einen Fehler werfen.

Verwandte Themen