2009-04-20 5 views
0

Ich habe ein Objekt, das ich MyObject nennen werde. Es ist eine Klasse, die eine bestimmte Datenzeile steuert.C# - Warum kann ich eine Liste <MyObject> nicht in eine Klasse umwandeln, die von der Liste <MyObject> erbt?

Ich habe dann eine Sammlung Klasse, MyObjectCollection genannt:

public class MyObjectCollection : List<MyObject> {} 

Warum kann ich folgendes nicht tun:

List<MyObject> list = this.DoSomethingHere(); 
MyObjectCollection collection = (MyObjectCollection)list; 

Vielen Dank im Voraus.

Edit: Der Fehler ist InvalidCastException

+0

Hoppla, Hit zu schnell zu schließen. Sieht aus, als wäre es nicht das Gleiche wie normal. –

+0

Wir brauchen ein bisschen mehr, um eine gute Antwort zu bekommen. Erhalten Sie einen Kompilierungsfehler? Was macht this.DoSomthingHere() zurück (Unterschrift und die "neue" Anweisung)? wenn ich weitere Informationen habe, werde ich mich bemühen zu antworten. –

Antwort

5

Meine Vermutung ist, dass DoSomethingHere keine Instanz MyObjectCollection zurückgibt.

Lassen Sie uns alle Generika usw. hier loswerden, da sie nicht relevant sind. Hier ist, was ich vermute, dass Sie versuchen zu tun:

public static object CreateAnObject() 
{ 
    return new object(); 
} 

object o = CreateAnObject(); 
string s = (string) o; 

Das wird (zur Ausführungszeit) und ganz zu Recht scheitern.

, um es wieder zu Ihrem Code, es sei denn, DoSomethingHeretatsächlich eine MyObjectCollection zur Ausführungszeit zurückkehrt, wird der Cast fehlschlagen.

+0

DoSomethingHere() ... Oder FindByAssetId (assetTypeId) im realen Fall gibt eine Liste oder eine Liste im realen Fall. Also, auch diese MyObjectCollection ist so ziemlich die Liste kann ich nicht verwenden, um zu casten? Scheint einfach so, als müsste es funktionieren! – GenericTypeTea

+0

Nein - Sie müssen auf die Vererbungskonzepte etwas mehr sorry lesen – ShuggyCoUk

+0

Nein, Sie können ein Objekt nicht auf einen anderen Typ umwandeln. Du könntest deinen eigenen Konverter schreiben, aber das klingt für mich nicht nach einer großartigen Idee. Was ist der Sinn von MyObjectCollection an erster Stelle? –

2

Ohne zu wissen, was genau innerhalb DoSomething() erzeugt wird, müssen wir davon ausgehen, entweder:

Sie ein Missverständnis über die inheritence in .Net haben.

Sie haben

A : B 

B DoSomething() 
{ 
    return new B(); 
} 
// then this is 
B b = new B(); 
A a = (A)b; 

Klar b a B ist aber kein A. B könnte ähnlich wie ein aussehen, aber es ist nicht (wenn Sie die Abstammungs der Traverse b Sie A überall nicht finden)

Dies gilt unabhängig von den beteiligten Generics (obwohl das manchmal Situationen führen kann, wo etwas, das die Co-contra Varianz in C# 4.0)

oder

nicht sehen arbeiten konnte

Welche in Abwesenheit von Generics wird arbeiten.

+0

Dank dafür, obwohl es nicht die Antwort war, die ich wählte, ließ es mich verstehen, warum es nicht funktionierte. Ich habe Jon als korrekt markiert, als er zuerst gepostet hat. – GenericTypeTea

+0

Das ist in Ordnung http://stackoverflow.com/questions/305223/jon-skeet-facts "Benutzer markieren Jon Skeets Antworten nicht als akzeptiert. Das Universum akzeptiert sie aus einem Gefühl von Wahrheit und Gerechtigkeit." ;) – ShuggyCoUk

1

Sie können es nicht, weil die Liste Instanz zurückgegeben von DoSomethingHere (I Erraten) nicht abgeleitet von MyObjectCollection

5

Da ein List<MyObject> kein MyObjectCollection ist. Das Umgekehrte ist wahr: Sie könnten eine MyObjectCollection in eine Liste umwandeln, weil MyObjectCollection von List<MyObject> erbt und somit IS A List<MyObject>.

Das einzige, was Sie tun können, ist einen Konstruktor auf MyObjectCollection zu definieren, die eine IEnumerable als Parameter übernehmen und initalizes selbst mit den Daten in der anderen, aber das wird ein neues Objekt mit den gleichen Daten machen:

UPDATE: Wie im Kommentar erwähnt, können Sie die Umwandlung zur Laufzeit erfolgreich sein, vorausgesetzt, dass DoSomething tatsächlich eine Instanz von MyObjectCollection zurückgibt. Wenn dies der Fall ist, ist das Objekt effektiv eine MyObjectCollection und die Besetzung ist vollständig legal.

ich sagen müsste, ist es schlechte Praxis in meiner Ansicht nach upcast so ähnlich. Wenn die Funktion eine Liste zurückgibt, sollten Sie sich nicht auf eine bestimmte Implementierung von List verlassen. Ändern Sie den Rückgabetyp von DoSomething, wenn Sie diese Funktion besitzen, und geben Sie eine MyObjectCollection zurück, oder behandeln Sie sie als Liste.

+0

Ich hätte das gerne gemacht, aber ich kann nur eine Instanz jeder Klasse haben, da alle darin enthaltenen Daten an einer Stelle verwaltet werden. – GenericTypeTea

+0

Ihre Aussage gilt zwar in einem allgemeinen Sinn (d. H. Jede Instanz der Liste ist keine MyObjectCollection) gilt nicht für jeden speziellen Fall einer Besetzung. Wenn der von 'DoSomething' zurückgegebene Wert tatsächlich eine MyObjectCollection ist, ist die Umwandlung erfolgreich, weil der zugrunde liegende Typ eine MyObjectCollection ist. –

+0

ziemlich wahr, Steve. Ich denke, ich war darauf konzentriert, warum er einen Fehler sah. Ich werde meine Antwort aktualisieren, da sie uplooted wurde, möchte keine falsche/teilweise Antwort auftauchen. Vielen Dank. –

0

Sie könnten einen impliziten Operator erstellen, die Sie erlauben würden, zwischen Objekt und der Liste zu konvertieren. Sie benötigen einen Konstruktor, der eine Liste übernimmt, und eine Eigenschaft, die die darunterliegende Liste zurückgibt.

public static implicit operator List<MyObject>(MyObjectCollection oCollection) 
{ 
    //Convert here 
    return MyObjectCollection.BaseList; 
} 

public static implicit operator MyObjectCollection(List<MyObject> oList) 
{ 
    //Convert here 
    return new MyObjectCollection(oList); 
} 
+0

Implizite Operatoren sind schlecht, schlecht, schlecht. Sie machen Code wirklich schwer zu lesen, können Bugs einführen, die schwer zu finden sind, und wirklich Maitain für jeden, der nicht der Autor war, aussaugen. – ctacke

+0

@ctacke - Wenn richtig wie in diesem Fall verwendet, dann sehe ich keinen Grund, sie nicht zu verwenden. Sie würden sich nicht über Int beschweren, um implizite Konvertierungen zu verdoppeln, würden Sie? Sie sind im Quellcode wie jeder andere Operator sichtbar. – stevehipwell

+0

int to double ist * garantiert * um in allen Fällen ohne dataloss zu arbeiten, wird normalerweise in lanagues ausgeführt, die standardmäßig nicht bigint/bigrational verwenden ... es gibt eine Welt von einem Unterschied – ShuggyCoUk

Verwandte Themen