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
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
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
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
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
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
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ß.
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
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ß.