2009-03-11 18 views
5

से कनवर्ट नहीं किया जा सकता है, मैंने हाल ही में किसी सूची में AddRange (IEnumerable) को आजमाने में परेशानी में भाग लिया है। शायद एक क्लासिक मुद्दा, लेकिन मुझे वास्तव में अभी तक यह नहीं मिला है।सी # IENumerable <Base> से IENumerable <Derived>

मैं समझता हूं कि सूची पैरामीटर की अपेक्षा करने वाली विधियां किसी सूची से संतुष्ट नहीं हैं, क्योंकि वे सूची में आधार जोड़ने का प्रयास कर सकते हैं, जो स्पष्ट रूप से असंभव है।

लेकिन अगर मुझे यह सही तरीके से मिलता है, क्योंकि IENumerables स्वयं को बदला नहीं जा सकता है, इसलिए इसे इस मामले में काम करना चाहिए।

कोड मैं इस तरह दिखता है के बारे में सोचा:

class Foo 
{ 
} 

class Bar : Foo 
{ 
} 

class FooCol 
{ 
    private List<Foo> m_Foos = new List<Foo>(); 

    public void AddRange1(IEnumerable<Foo> foos) 
    { 
     m_Foos.AddRange (foos); // does work 
    } 

    public void AddRange2<T>(IEnumerable<T> foos) where T : Foo 
    { 
     m_Foos.AddRange (foos); // does not work 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     FooCol fooCol = new FooCol(); 

     List<Foo> foos = new List<Foo>(); 
     List<Bar> bars = new List<Bar>(); 

     fooCol.AddRange1 (foos); // does work 
     fooCol.AddRange1 (bars); // does not work 

     fooCol.AddRange2 (foos); // does work 
     fooCol.AddRange2 (bars); // does work 
    } 
} 

मैं AddRange2 विधि में संकलक करने के लिए एक संकेत के पारित करने के लिए कोशिश की, लेकिन यह सिर्फ चारों ओर समस्या के लिए ले जाया गया।

क्या सोचने का मेरा तरीका त्रुटिपूर्ण है? क्या यह भाषा का एक सीमा है या यह डिजाइन द्वारा है?

आईआईआरसी, इस तरह के संचालन के लिए समर्थन जावा 1.5 में जोड़ा गया था, तो हो सकता है कि इसे भविष्य में किसी भी समय सी # में जोड़ा जाएगा ...?

+0

हाल ही में http://stackoverflow.com/questions/632399 –

+0

सहित कई अन्य प्रश्नों का डुप्लिकेट, मुझे खेद है। मेरे google-jutsu अभी भी सुधार की जरूरत है। – mafu

+0

कोई समस्या नहीं है। प्रति टैग एफएक्यू, आईएमओ होना अच्छा लगेगा ... –

उत्तर

18

यह कॉन्वर्सिस है, और इसे सी # 4.0/.NET 4.0 में तय किया जाएगा। अभी के लिए, सामान्य विकल्प सबसे अच्छा जवाब है (IEnumerable<T> - not IList<T> etc के लिए)।

लेकिन सामान्य विधि के भीतर, आपको T के संदर्भ में विचार करना होगा। आप कुछ समान प्राप्त करने के लिए LINQ के साथ Cast<T> या OfType<T> का भी उपयोग कर सकते हैं।

+1

नए शब्द, कॉन्वर्सिस के लिए धन्यवाद। अस्तित्व के बारे में नहीं पता था। – Sung

0

विस्तार विधि के साथ वैकल्पिक हल नहीं है:

public static IEnumerable<TBase> ToBaseEnumerable<TBase, TDerived>(this IEnumerable<TDerived> items) where TDerived : TBase { 
    foreach(var item in items) { 
     yield return item; 
    } 
} 
... 
IEnumerable<Employee> employees = GetEmployees(); //Emplyoee derives from Person 
DoSomethingWithPersons(employees.ToBaseEnumerable<Person, Employee>()); 

लेकिन "< व्यक्ति, कर्मचारी>" है छोटा सा अजीब: /।

+0

कास्ट () आसान होगा ... –

2

सी # 3.0 में आप "कास्ट" एक्सटेंशन विधि का उपयोग कर सकते हैं। यदि आप System.Linq आयात करते हैं और फिर इस कोड का उपयोग करते हैं:

public void AddRange2<T>(IEnumerable<T> foos) where T : Foo 
{ 
    m_Foos.AddRange (foos.Cast<Foo>()); 
} 

फिर यह आपके लिए काम करना चाहिए।

0

कोर्स का कास्ट समाधान क्लास कास्ट अपवाद उत्पन्न कर सकता है। जिस व्यक्ति ने समेकित विस्तार कार्य पोस्ट किया वह कहता है कि यह अजीब था। मैं एक समाधान है जो केवल अजीब के रूप में आधा है के साथ आया था, पता नहीं है अगर मैं इसे का उपयोग करेंगे:

public static class UpTo<T> 
{ 
    public static IEnumerable<T> From<F>(IEnumerable<F> source) where F:T 
    { 
     // this cast is guaranteed to work 
     return source.Select(f => (T) f); 
    } 
} 

उपयोग:

IEnumerable स्तनधारियों = तक < स्तनपायी > .From (kennel। कुत्तों)

संबंधित मुद्दे