2010-07-04 3 views
7

Ich habe eine Klasse erstellt, die von List abgeleitet ist. Wenn ich jedoch versuchte, die Klasse in ein anderes List-Objekt umzuwandeln, erhalte ich einen Laufzeitfehler. Mein Code ist ähnlich dem unten geschrieben:Umwandlung einer generischen Liste in eine von einer Liste abgeleitete Klasse

public class CategoryObj 
{ 
    public int CategoryID { get; set; } 
    public string CategoryName { get; set; } 
    public string Description { get; set; } 
} 

public class CategoryObjCollection:List<CategoryObj> 
{ 

} 

public void Test() 
{ 
     CategoryObjCollection cat = new CategoryObjCollection(); 
     using (NWDataContext db = new NWDataContext()) 
     { 
      var qry = (from c in db.Categories 
         select new CategoryObj 
         { 
          CategoryID = c.CategoryID, 
          CategoryName = c.CategoryName, 
          Description = c.Description 
         }).ToList(); 
      cat = (CategoryObjCollection)qry; //runtime error Unable to cast object of type 'System.Collections.Generic.List`1[WindowsFormsApplication1.CategoryObj]' to type 'WindowsFormsApplication1.CategoryObjCollection'. 
     } 
} 

Ich hoffe, dass jemand mir auf diesem helfen kann. Vielen Dank.

Antwort

6

versuchen diese

public class CategoryObjCollection:List<CategoryObj> 
{ 
    public CategoryObjCollection(IEnumerable<CategoryObj> items) : base(items){} 
} 


cat = new CategoryObjCollection(qry); 
12

Warum würden Sie werfen zu können, erwarten? Das Objekt ist nicht eine Instanz von CategoryObjCollection. Der Punkt der Referenztyp-Umwandlungen (wenn sie tatsächlich deklarieren, anstatt explizite Konvertierungen aufzurufen) besteht darin, dem Compiler mitzuteilen, dass der Ausführungszeitpunkt des Objekts tatsächlich mit dem von Ihnen angegebenen Typ kompatibel ist, so dass Sie ihn verwenden können Mitglieder dieses spezifischen Typs (nach dem Ausführungszeittest). In diesem Fall erstellt die Erweiterungsmethode ToList nur eine neue List<T>.

Mehr auf den Punkt, was ist Ihr CategoryObjCollection Art, um in erster Linie zu erreichen? Wenn es einen anderen Status als die normale Liste gibt, wo würden Sie nach der LINQ-Abfrage von diesem Status erwartet? Wenn es keinen anderen Zustand hat, fügt es wirklich irgendeinen Nutzen hinzu? Vielleicht sollte Ihr Typ eigentlich eine Liste enthalten anstatt daraus abzuleiten? Dann könnten Sie mithilfe der Ergebnisse der Abfrage eine neue Instanz des Typs erstellen.

Im Allgemeinen ist es normalerweise ein Designgeruch, der von List<T> abgeleitet wird. Es bietet nicht viele Möglichkeiten, seine "Listenhaftigkeit" zu spezialisieren (anders als beispielsweise Collection<T>). Es ist normalerweise ein Zeichen, dass Sie an die Zusammensetzung statt an die Vererbung denken sollten.

+0

Sieht für mich so aus, als würde er versuchen, einen C++ - ähnlichen Typedef-Alias ​​zu erstellen. –

+0

@ Jaroslav: Ziemlich wahrscheinlich - aber das ist nicht, was Vererbung ist, und es ist nicht, wofür es verwendet werden sollte. –

+0

In der Tat. Dafür ist die "using" -Richtlinie gedacht. –

3

Die Besetzung würde nur funktionieren, wenn Sie einen Konvertierungsoperator implementiert haben. Aber es ist kein sehr effektiver Ansatz.

Versuchen Sie einen Typalias zu erstellen (wie in C++ typedef)?

using CategoryObjCollection = System.Collections.Generic.List<myNamespace.CategoryObj>; 

Jetzt können Sie frei konvertieren zwischen CategoryObjCollection und List<CategoryObj> (die die gleiche Art ist - nur anders genannt

ich auch eine andere Methode verwenden würden, um die Liste zu füllen.

db.Categories.ForEach(c => 
    cat.Add(new CategoryObj() 
     { 
      CategoryID = c.CategoryID, 
      CategoryName = c.CategoryName, 
      Description = c.Description 
     })); 
0

warum Sie Casting? Sie sollten eigentlich nicht Gießen .... fügen Sie einfach eine Schleife über und füllen Sie Ihre cat Liste auf.

Verwandte Themen