Sweko'nun noktasına eklemek için:
Oyuncunun neden olmasının nedeni
var listOfX = new List<X>();
ListOf<Y> ys = (List<Y>)listOfX; // Compile error: Cannot implicitly cast X to Y
mümkün değildir çünkü List<T>
olan Tip T değişmez ve böylece olmadığını önemli değil X
kaynaklanmaktadır Y
) - bunun nedeni olduğu List<T>
gibi tanımlanmıştır:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T> ... // Other interfaces
(Bu bildirimde, T
buraya yazmanın ek varyans değiştiricileri olmadığını unutmayın)
Değişken koleksiyonları tasarım, değişmez koleksiyonlarının birçoğunda yukarı çevrim içinde gerekli değilse Ancak, mümkün örneğin şartıyla Giraffe
dan türemiştir Animal
:
IEnumerable<Animal> animals = giraffes;
Bunun nedeni IEnumerable<T>
kovaryansın desteklenmesidir T
- bu IEnumerable
, koleksiyona öğe ekleme veya toplama yöntemleri için desteği olmadığı için koleksiyonun değiştirilemeyeceği anlamına gelir. out
Anahtar kelimeyi beyanında not edin IEnumerable<T>
:
public interface IEnumerable<out T> : IEnumerable
( Değişmez yineleyiciler ve koleksiyonlar neden desteklenebilir gibi değişmez koleksiyonların neden desteklenemediğine dair daha fazla açıklama .)List
covariance
İle yayınlanıyor .Cast<T>()
Diğerlerinin de belirttiği gibi, .Cast<T>()
T'ye InvalidCastException
dökülen yeni bir eleman koleksiyonunu yansıtmak için bir koleksiyona uygulanabilir, ancak bunu yapmak bir veya daha fazla elemanın dökümü mümkün değilse (açık olanla aynı davranış olacaktır) OP foreach
döngüsünde döküm ).
Filtreleme ve Döküm OfType<T>()
Giriş listesi farklı, uyumsuz türden öğeler içeriyorsa, bunun yerine InvalidCastException
kullanılarak potansiyelden kaçınılabilir . ( dönüştürmeyi denemeden önce bir öğenin hedef türe dönüştürülüp dönüştürülemeyeceğini kontrol eder ve uyumsuz türleri filtreler.).OfType<T>()
.Cast<T>()
.OfType<>()
her biri için
(Not: Ayrıca OP yerine bu yazılı olsaydı unutmayın açıkY y
içinde foreach
)
List<Y> ListOfY = new List<Y>();
foreach(Y y in ListOfX)
{
ListOfY.Add(y);
}
döküm de denenecek. Ancak, oyuncu seçimi mümkün değilse, bir InvalidCastException
irade ortaya çıkar.
Örnekler
Örneğin, basit (C # 6) sınıf hiyerarşisi göz önüne alındığında:
public abstract class Animal
{
public string Name { get; }
protected Animal(string name) { Name = name; }
}
public class Elephant : Animal
{
public Elephant(string name) : base(name){}
}
public class Zebra : Animal
{
public Zebra(string name) : base(name) { }
}
Karışık tiplerden oluşan bir koleksiyonla çalışırken:
var mixedAnimals = new Animal[]
{
new Zebra("Zed"),
new Elephant("Ellie")
};
foreach(Animal animal in mixedAnimals)
{
// Fails for Zed - `InvalidCastException - cannot cast from Zebra to Elephant`
castedAnimals.Add((Elephant)animal);
}
var castedAnimals = mixedAnimals.Cast<Elephant>()
// Also fails for Zed with `InvalidCastException
.ToList();
Buna karşılık:
var castedAnimals = mixedAnimals.OfType<Elephant>()
.ToList();
// Ellie
sadece Filleri filtreler - yani Zebralar elenir.
Re: Örtülü döküm operatörleri
Dinamik olmadan, kullanıcı tanımlı dönüşüm işleçleri yalnızca derleme zamanında * kullanılır, bu nedenle Zebra ve Fil arasında bir dönüştürme operatörü kullanıma sunulmuş olsa bile, dönüşüm yaklaşımlarının yukarıdaki çalışma süresi davranışı değişmez.
Zebra'yı Fil'e dönüştürmek için bir dönüşüm operatörü eklersek:
public class Zebra : Animal
{
public Zebra(string name) : base(name) { }
public static implicit operator Elephant(Zebra z)
{
return new Elephant(z.Name);
}
}
Bunun yerine, yukarıda dönüşüm operatör verilen derleyici dizisi aşağıdaki türünü değiştirmek mümkün olacaktır Animal[]
için Elephant[]
Zebralar hemen Filler homojen bir toplama dönüştürülebilir verilen:
var compilerInferredAnimals = new []
{
new Zebra("Zed"),
new Elephant("Ellie")
};
Örtük Dönüştürme İşleçlerini çalışma zamanında kullanma
* Eric tarafından belirtildiği gibi, dönüşüm operatörüne aşağıdaki koşullarda başvurarak çalışma zamanında erişilebilir dynamic
:
var mixedAnimals = new Animal[] // i.e. Polymorphic collection
{
new Zebra("Zed"),
new Elephant("Ellie")
};
foreach (dynamic animal in mixedAnimals)
{
castedAnimals.Add(animal);
}
// Returns Zed, Ellie