एरिक के महान विवरण को उद्धृत करने के लिए
क्या होता है? क्या आप चाहते हैं कि जिराफ की सूची में बाघ हो? क्या आप एक दुर्घटना चाहते हैं? या क्या आप चाहते हैं कि संकलक आपको पहले स्थान पर असाइनमेंट को अवैध बनाकर दुर्घटना से बचाए? हम बाद का चयन करते हैं।
लेकिन क्या होगा यदि आप एक संकलन त्रुटि के बजाय एक रनटाइम क्रैश के लिए चुनना चाहते हैं? आप आम तौर पर कास्ट <या ConvertAll <> का उपयोग करेंगे, लेकिन फिर आपको 2 समस्याएं होंगी: यह सूची की एक प्रति तैयार करेगा। यदि आप नई सूची में कुछ जोड़ते या हटाते हैं, तो यह मूल सूची में परिलक्षित नहीं होगा। और दूसरी बात, एक बड़ा प्रदर्शन और मेमोरी पेनल्टी है क्योंकि यह मौजूदा वस्तुओं के साथ एक नई सूची बनाता है।
मुझे भी यही समस्या थी और इसलिए मैंने एक रैपर क्लास बनाई, जो पूरी तरह से नई सूची बनाए बिना एक जेनेरिक सूची तैयार कर सकती है।
मूल प्रश्न में आप तब उपयोग कर सकते हैं:
class Test
{
static void Main(string[] args)
{
A a = new C(); // OK
IList<A> listOfA = new List<C>().CastList<C,A>(); // now ok!
}
}
और यहाँ रैपर क्लास (+ आसान उपयोग के लिए एक एक्सट्रैक्शन विधि कास्टलिस्ट)
public class CastedList<TTo, TFrom> : IList<TTo>
{
public IList<TFrom> BaseList;
public CastedList(IList<TFrom> baseList)
{
BaseList = baseList;
}
// IEnumerable
IEnumerator IEnumerable.GetEnumerator() { return BaseList.GetEnumerator(); }
// IEnumerable<>
public IEnumerator<TTo> GetEnumerator() { return new CastedEnumerator<TTo, TFrom>(BaseList.GetEnumerator()); }
// ICollection
public int Count { get { return BaseList.Count; } }
public bool IsReadOnly { get { return BaseList.IsReadOnly; } }
public void Add(TTo item) { BaseList.Add((TFrom)(object)item); }
public void Clear() { BaseList.Clear(); }
public bool Contains(TTo item) { return BaseList.Contains((TFrom)(object)item); }
public void CopyTo(TTo[] array, int arrayIndex) { BaseList.CopyTo((TFrom[])(object)array, arrayIndex); }
public bool Remove(TTo item) { return BaseList.Remove((TFrom)(object)item); }
// IList
public TTo this[int index]
{
get { return (TTo)(object)BaseList[index]; }
set { BaseList[index] = (TFrom)(object)value; }
}
public int IndexOf(TTo item) { return BaseList.IndexOf((TFrom)(object)item); }
public void Insert(int index, TTo item) { BaseList.Insert(index, (TFrom)(object)item); }
public void RemoveAt(int index) { BaseList.RemoveAt(index); }
}
public class CastedEnumerator<TTo, TFrom> : IEnumerator<TTo>
{
public IEnumerator<TFrom> BaseEnumerator;
public CastedEnumerator(IEnumerator<TFrom> baseEnumerator)
{
BaseEnumerator = baseEnumerator;
}
// IDisposable
public void Dispose() { BaseEnumerator.Dispose(); }
// IEnumerator
object IEnumerator.Current { get { return BaseEnumerator.Current; } }
public bool MoveNext() { return BaseEnumerator.MoveNext(); }
public void Reset() { BaseEnumerator.Reset(); }
// IEnumerator<>
public TTo Current { get { return (TTo)(object)BaseEnumerator.Current; } }
}
public static class ListExtensions
{
public static IList<TTo> CastList<TFrom, TTo>(this IList<TFrom> list)
{
return new CastedList<TTo, TFrom>(list);
}
}