Laden...

List<Unterklasse> auf List<Oberklasse> casten

Erstellt von Howard vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.898 Views
Howard Themenstarter:in
84 Beiträge seit 2007
vor 14 Jahren
List<Unterklasse> auf List<Oberklasse> casten

Hallo Leudde ich hab da mal nen Prob:
gegeben sei folgendes



public interface IKontaktDaten {....}

public interface IFirma : IKontaktDaten{....}

public interface IPerson : IKontaktDaten{....}

public class Firma : IFirma {....}

public class Person : IPerson {....}

public List<T> GetKontaktList<T>() where T: IKontaktDaten, new(){...}

public void Function()
{
	List<IKontaktDaten>	listKontakte; //IKontaktDaten da ich in diese Liste gern beides Firma UND Person reinladen würde
	
	listKontakte = GetKontaktList<Person>(); //<-- Eine implizite Konvertierung vom Typ "System.Collections.Generic.List<Person>" in "System.Collections.Generic.List<IKontaktDaten>" ist nicht möglich.

	
	//Ich würde gern danach sowas machen
	listKontakte = GetKontaktList<Firma>();
}

//Alternativ kann man das natürlich so machen
public void Function()
{
	List<IFirma>	listFirmen;
	List<IPerson>	listPerson;
	
	listPerson = GetKontaktList<Person>();		
	listFirmen = GetKontaktList<Firma>();
}

Irgendwie hab da wohl noch was nicht ganz verstanden mit den Generics. Klar kann ich 2 Listen machen aber einfacher wäre eine.
Hat da wer mal ne Idee??

Howard

998 Beiträge seit 2007
vor 14 Jahren

Hallo,

listKontakte ist eine Liste vom Typ IKontaktDaten und du versuchst eine List<Person> darein zu konvertieren, obowhl Person nicht von IKontaktDaten ableitet (Person -> IPerson -> IKontakt -> IFirma)

Gruß David

Howard Themenstarter:in
84 Beiträge seit 2007
vor 14 Jahren

jo okay wenns soooo einfach wäre wär geil 😁 ich hatte nen schreibfehler drinn hab den mal verbessert....
Aber danke für den Hinweis....

Howard

49.485 Beiträge seit 2005
vor 14 Jahren
Howard Themenstarter:in
84 Beiträge seit 2007
vor 14 Jahren

Hey vielen Dank für den Link.
Allerdings ist mir nicht ganz klar wie deine Klasse mir bei meinem Prob helfen kann und wie/wo ich sie dann einbaun soll DAMIT sie mir hilft 😃

Howard

2.891 Beiträge seit 2004
vor 14 Jahren

Hallo Howard,

List<Unterklasse> auf List<Oberklasse> casten

Das geht bis .NET 3.5 nicht. Grund ist folgender: Wenn du eine List<IPerson> in eine List<IKontakt> casten könntest, dann würden die list.Item-Methode etwas allgemeineres zurückgeben, als in der Liste drin ist. Das wäre auch problemlos möglich, genau in diese Richtung willst du ja auch.
Allerdings nimmt die Add-Methode einer List<IKontakt> alle IKontakt-Objekte an. Du würdest dann also auch ein IFirma-Objekt hinzufügen können, obwohl es aber eine List<IPerson> ist. Diese Richtung geht dann völlig in die Hose.

Denkbar wäre auch ein Szenario "in die andere Richtung". Auf jeden Fall geht nur eins: Entweder, der Rückgabetyp der Methoden mit Typ der Oberklasse (Kovarianz), oder Parameter für Methoden mit Typ der Oberklasse (Kontravarianz). Beides zusammen ist nicht möglich.
Daher gibt es ab .NET 4.0 den in- und out-Modifikator, um Ko- und Kontravarianz in Generika ausdrücken zu können.

Für .NET <4.0 gilt daher: Casten geht nicht, du musst die gesamte Liste konvertieren. Dabei hilft dir dann auch der vorgeschlagene Wrapper (der die Kovarianz realisiert).

Gruß,
dN!3L

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Howard,

Das geht bis .NET 3.5 nicht.

und genau deshalb hilft der Wrapper. Das Erzeugen des Wrappers ist der Ersatz für den Cast.

herbivore

1.564 Beiträge seit 2007
vor 14 Jahren

Hallo Howard

Wenn nicht zu viele Werte in der Liste sind und die Performance nicht kritisch ist kannst du auch LINQ verwenden:

         List<IList<int>> list = new List<IList<int>>();

         // ... fill

         List<List<int>> list2 = list.Cast<List<int>>().ToList();
         List<List<int>> list3 = list.ConvertAll<List<int>>(l => (List<int>)l);

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

Howard Themenstarter:in
84 Beiträge seit 2007
vor 14 Jahren

Wenn nicht zu viele Werte in der Liste sind und die Performance nicht kritisch ist kannst du auch LINQ verwenden:

ich dachte das gibts erst ab VS2008 oder?

Howard

1.564 Beiträge seit 2007
vor 14 Jahren

Hatte darauf nicht geachtet. Dann kannst du meinen Post vergessen.

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.