स्वेको के बिंदु में जोड़ने के लिए:
जिस कारण कलाकारों ने
var listOfX = new List<X>();
ListOf<Y> ys = (List<Y>)listOfX; // Compile error: Cannot implicitly cast X to Y
संभव नहीं है क्योंकि है List<T>
है प्रकार टी में अपरिवर्तनीय और इस तरह यह है कि क्या बात नहीं है X
से व्युत्पन्न Y
) - इसका कारण यह है List<T>
के रूप में परिभाषित किया गया है:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T> ... // Other interfaces
(ध्यान दें कि इस घोषणा में, T
यहाँ कोई अतिरिक्त प्रसरण संशोधक नहीं है)
हालाँकि, अगर आपके डिज़ाइन में उत्परिवर्तनीय संग्रह की आवश्यकता नहीं है, तो कई अपरिवर्तनीय संग्रहों पर एक उपहास संभव है , उदाहरण के लिए, जो इससे Giraffe
प्राप्त होता है Animal
:
IEnumerable<Animal> animals = giraffes;
ऐसा इसलिए है क्योंकि यह IEnumerable<T>
सहसंयोजक का समर्थन करता है T
- इससे यह समझ में आता है कि IEnumerable
इसका मतलब है कि संग्रह को बदला नहीं जा सकता है, क्योंकि इसमें संग्रह से तत्वों को जोड़ने या हटाने के तरीकों का कोई समर्थन नहीं है। out
की घोषणा में कीवर्ड पर ध्यान दें IEnumerable<T>
:
public interface IEnumerable<out T> : IEnumerable
( यहां इस कारण के बारे में और अधिक विवरण दिया गया है कि क्यों परस्पर संग्रह जैसे List
समर्थन का समर्थन नहीं किया जा सकता है covariance
, जबकि अपरिवर्तनीय पुनरावृत्तियों और संग्रह कर सकते हैं।)
के साथ कास्टिंग .Cast<T>()
जैसा कि दूसरों ने उल्लेख किया है, .Cast<T>()
टी के InvalidCastException
लिए डाले गए तत्वों के एक नए संग्रह को प्रस्तुत करने के लिए एक संग्रह पर लागू किया जा सकता है, हालांकि ऐसा करने से एक या अधिक तत्वों पर डाली संभव नहीं होगी (जो कि स्पष्ट करने के समान व्यवहार होगा) ओपी के foreach
पाश में डाली गई )।
के साथ फ़िल्टरिंग और कास्टिंग OfType<T>()
यदि इनपुट सूची में अलग-अलग, असंगत प्रकार के तत्व हैं, तो इसके बजाय का InvalidCastException
उपयोग करके संभावित से बचा जा सकता .OfType<T>()
है .Cast<T>()
। ( .OfType<>()
यह देखने के लिए जाँच करता है कि रूपांतरण का प्रयास करने से पहले एक तत्व को लक्ष्य प्रकार में परिवर्तित किया जा सकता है या असंगत प्रकारों को फ़िल्टर करता है।)
प्रत्येक के लिए
यह भी ध्यान दें कि यदि ओपी ने इसके बजाय यह लिखा है: ( स्पष्टY y
में नोट करें foreach
)
List<Y> ListOfY = new List<Y>();
foreach(Y y in ListOfX)
{
ListOfY.Add(y);
}
कि कास्टिंग का भी प्रयास किया जाएगा। हालांकि, अगर कोई कास्ट संभव नहीं है, तो एक InvalidCastException
परिणाम होगा।
उदाहरण
उदाहरण के लिए, दी गई सरल (C # 6) श्रेणी पदानुक्रम:
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) { }
}
मिश्रित प्रकारों के संग्रह के साथ काम करते समय:
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();
जहाँ तक:
var castedAnimals = mixedAnimals.OfType<Elephant>()
.ToList();
// Ellie
केवल हाथियों को फ़िल्टर करता है - अर्थात ज़ेब्रा को समाप्त कर दिया जाता है।
पुन: अवैध डाली ऑपरेटरों
डायनामिक के बिना, उपयोगकर्ता परिभाषित रूपांतरण ऑपरेटर केवल संकलन-समय * पर उपयोग किए जाते हैं , इसलिए भले ही ज़ेबरा और एलिफेंट के बीच एक रूपांतरण ऑपरेटर उपलब्ध कराया गया हो, रूपांतरण के लिए दृष्टिकोणों के उपरोक्त समय व्यवहार में परिवर्तन नहीं होगा।
यदि हम एक ज़ेबरा को एक हाथी में बदलने के लिए एक रूपांतरण ऑपरेटर जोड़ते हैं:
public class Zebra : Animal
{
public Zebra(string name) : base(name) { }
public static implicit operator Elephant(Zebra z)
{
return new Elephant(z.Name);
}
}
इसके बजाय, ऊपर रूपांतरण ऑपरेटर को देखते हुए संकलक सरणी के नीचे से के प्रकार को बदलने में सक्षम हो जाएगा Animal[]
करने के लिए Elephant[]
, यह देखते हुए कि जेब्रा अब हाथियों का एक सजातीय संग्रह करने के लिए परिवर्तित किया जा सकता है:
var compilerInferredAnimals = new []
{
new Zebra("Zed"),
new Elephant("Ellie")
};
रन टाइम में इंप्लिकेंट कनवर्ज़न ऑपरेटर्स का उपयोग करना
* जैसा कि एरिक ने उल्लेख किया है, रूपांतरण ऑपरेटर को समय का सहारा लेकर चलाया जा सकता है 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