public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Wie kann ich werfen List<Client>
zu List<IDic>
?
public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Wie kann ich werfen List<Client>
zu List<IDic>
?
Antworten:
Sie können es nicht umsetzen (Referenzidentität bewahren) - das wäre unsicher. Beispielsweise:
public interface IFruit {}
public class Apple : IFruit {}
public class Banana : IFruit {}
...
List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());
// Eek - it's a banana!
Apple apple = apples[0];
Jetzt können Sie aufgrund von Kovarianz eine List<Apple>
in eine IEnumerable<IFruit>
in .NET 4 / C # 4 konvertieren. Wenn Sie jedoch eine möchten, müssen List<IFruit>
Sie eine neue Liste erstellen . Beispielsweise:
// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();
// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();
Dies ist jedoch nicht dasselbe wie das Casting der ursprünglichen Liste - da es jetzt zwei separate Listen gibt. Dies ist sicher, aber Sie müssen verstehen, dass Änderungen an einer Liste nicht in der anderen Liste angezeigt werden. (Änderungen an den Objekten , auf die sich die Listen beziehen, werden natürlich angezeigt.)
List<IFruit>
die tatsächlich eine Referenz auf a war List<Apple>
. Was würden Sie erwarten, wenn Sie einen Banana
Verweis darauf hinzufügen würden List<IFruit>
?
using
Richtlinie für System.Linq
, oder was Sie versuchen , es zu nennen, ich bin sicher , dass nicht , wie du mich erwarten zu Hilfe zu können. Ich schlage vor, Sie recherchieren mehr und wenn Sie immer noch nicht weiterkommen, stellen Sie eine Frage mit einem minimal reproduzierbaren Beispiel .
Ein Cast-Iterator und .ToList ():
List<IDic> casted = input.Cast<IDic>().ToList()
wird den Trick machen.
Ursprünglich sagte ich, Kovarianz würde funktionieren - aber wie Jon zu Recht betont hat; nein wird es nicht!
Und ursprünglich habe ich den ToList()
Anruf auch dumm abgebrochen
Cast
eine Rendite IEnumerable<T>
, keine List<T>
- und nein, Kovarianz nicht um diese Umwandlung zu ermöglichen, da es unsicher wäre - meine Antwort sehen.
ToList()
fehlte, bevor ich Ihren Kommentar gelesen habe. Aber ja, wie Sie gezeigt haben, funktioniert Covariance natürlich nicht! Doh!
Cast
Aufruf in .NET 4 nicht benötigen , solange Sie das Typargument angeben ToList
.
Auch ich hatte dieses Problem und nachdem ich Jon Skeets Antwort gelesen hatte, änderte ich meinen Code von der Verwendung List<T>
zur Verwendung IEnumerable<T>
. Obwohl dies nicht die OP ursprüngliche Frage beantwortet Wie kann ich werfen List<Client>
zuList<IDic>
, ist es die Notwendigkeit zu vermeiden , dies zu tun, und kann somit für andere hilfreich sein , die dieses Problem auftreten. Dies setzt natürlich voraus, dass der Code, für den die Verwendung erforderlich List<IDic>
ist, unter Ihrer Kontrolle steht.
Z.B:
public void ProcessIDic(IEnumerable<IDic> sequence)
{
// Implementation
}
Anstatt:
public void ProcessIDic(List<IDic> list)
{
// Implementation
}
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
Es ist nur möglich, indem Sie neue List<IDic>
Elemente erstellen und alle Elemente übertragen.
In .Net 3.5 können Sie Folgendes tun:
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
Der Konstruktor für List verwendet in diesem Fall eine IEnumerable.
Liste ist jedoch nur in IEnumerable konvertierbar. Obwohl myObj möglicherweise in ISomeInterface konvertierbar ist, kann der Typ IEnumerable nicht in IEnumerable konvertiert werden.