2016-08-30 8 views
6

IEnumerable<T1> कोविरिएट IEnumerable<T2> पर जांचने के लिए आम नियम क्या है?'IENumerable <T1>' को 'IENumerable <T2>' के लिए 'covariant' की जांच कैसे करें?

मैं कुछ प्रयोग किए हैं:


1.

Object Obj = "Test string"; 
IEnumerable<Object> Objs = new String[100]; 

वर्क्स क्योंकि IEnumerable<out T> covariant है और String विरासत Object

2.

interface MyInterface{} 
struct MyStruct:MyInterface{} 
..... 
Object V = new MyStruct(); 
Console.WriteLine(new MyStruct() is Object); // Output: True. 
IEnumerable<Object> Vs = new MyStruct[100]; // Compilation error here 

MyStruct वास्तव में एक Object है, लेकिन यह काम नहीं करता है क्योंकि Object संदर्भ प्रकार है और MyStruct मूल्य प्रकार है। ठीक है, मैं यहां कुछ तर्क देखता हूं।

3.

Console.WriteLine(new MyStruct() is ValueType); // Output: "True" 
ValueType V2 = new MyStruct(); 
IEnumerable<ValueType> Vs2 = new MyStruct[100]; // Compilation error here 

काम करना चाहिए क्योंकि IEnumerable<out T> covariant है और MyStructValueType है, लेकिन काम नहीं करता है ... ठीक है, हो सकता है MyStructValueType inheritst वास्तव में नहीं है ....

4.

MyInterface V3 = new MyStruct(); 
Console.WriteLine(V3 is MyInterface); // Output: "True" 
IEnumerable<MyInterface> Vs3 = new MyStruct[100]; // Compilation error here 

यहां तक ​​कि इस तरह से: "MyStterface में MyStruct को परिवर्तित नहीं कर सकता"। क्या सचमे?? तुम बस यह एक पंक्ति से पहले ...


मैं आम नियम तैयार करने के लिए कोशिश की है आपने क्या किया:

public static bool IsCovariantIEnumerable(Type T1, Type T2 ){   
    return (T2.IsAssignableFrom(T1)) && !T2.IsValueType; // Is this correct?? 
} 

तो, सवाल कैसे वास्तव में निर्धारित करने के लिए करता है, तो IEnumerable<T1>IEnumerable<T2> को covariant है ? क्या मेरा IsCovariantIEnumerable(...) सही है? यदि हां, तो इसे जांचने का कोई आसान तरीका है? यदि नहीं, तो इसे कैसे ठीक करें?

इन लेखों को भी देखें: 1, 2

+0

मूल्य प्रकार केवल सह-भिन्नता का समर्थन नहीं करते हैं; यह आश्चर्यजनक नहीं होना चाहिए कि मूल्य प्रकार * विरासत * का समर्थन नहीं करते हैं। यदि आपको किसी मान प्रकार को इंटरफ़ेस और/या 'ऑब्जेक्ट' के रूप में उपयोग करने की आवश्यकता है, तो आपको इसे बॉक्स करने की आवश्यकता है - उदा। 'Array.Cast '। यह स्पष्ट नहीं है कि इसका कौन सा हिस्सा आपको समझ में नहीं आता है, बशर्ते आपके द्वारा जुड़े प्रश्नों को भी इस प्रश्न का उत्तर दें :) – Luaan

+0

@ लुआयन, मैं सिर्फ यह जांचने के लिए पूर्ण नियम रखना चाहता हूं कि 'IENumerable 'कोविएरिएट' IENumerable '। मुझे अभी भी यकीन नहीं है कि मेरा 'IsCovariantIEnumerable() 'फ़ंक्शन सही है या नहीं। – Astronavigator

+1

इंटरफेस का समर्थन करने के मामले में, ['IsAssignableFrom'] (https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom (v = vs.110) .aspx)' IsSubclassOf से बेहतर कर सकता है ' – grek40

उत्तर

5

अपने विशिष्ट मामले में क्योंकि मूल्य प्रकार सह विचरण का समर्थन नहीं करते यह काम नहीं करता।

लेकिन सवाल यह निर्धारित करने के लिए कैसे अगर एक IEnumerable<T2>IEnumerable<T1> को सह-संस्करण है के लिए:

विधि Type.IsAssignableFrom() आपको बताता है कि एक खास प्रकार का एक उदाहरण इस प्रकार का एक चर के लिए assignalbe है। तो अगर आप इस तरह अपने विधि को लागू कर सकते हैं:

public static bool IsCovariantIEnumerable(Type T1, Type T2) 
{ 
    Type enumerable1 = typeof(IEnumerable<>).MakeGenericType(T1); 
    Type enumerable2 = typeof(IEnumerable<>).MakeGenericType(T2); 
    return enumerable1.IsAssignableFrom(enumerable2); 
} 

उपयोग:

if (IsCovariantIEnumerable(typeof(object), typeof(string)) 
    Console.WriteLine("IEnumerable<string> can be assigned to IEnumerable<object>"); 

लेकिन IsCovariantIEnumerable(typeof(object), typeof(MyStruct)) कारण ऊपर कहा गया है के लिए अवास्तविक लौटाते हैं।


पूर्णता के लिए: बेशक आप एक अतिरिक्त विधि के रूप में आप आसानी से typeof(IEnumerable<object>).IsAssignableFrom(typeof(IEnumerable<string>) कर सकते हैं की जरूरत नहीं है।

+0

असल में 'IENumerable <...> 'असाइन करने योग्यता की जांच करना आइटम प्रकार व्यवहार का अनुमान लगाने के दूसरे से अधिक सीधे आगे है। स्वच्छ समाधान, मैंने नहीं सोचा था। – grek40

+0

@ grek40 आप सही हैं, मैं ओपी के विधि कार्यान्वयन के बारे में सोच रहा था और इस प्रकार 'IsAssignableFrom' को सीधे कॉल भूल गया था। इसे पूर्णता के लिए जोड़ा गया। –

+0

मुझे लगता है कि आपका 'IsCovariantIEnumerable' ठीक काम करता है। लेकिन अभी भी सवाल यह है: "क्या मेरा 'IsCovariantIEnumerable' भी सही है या नहीं?" क्या कोई उदाहरण है जहां आपका कार्य काम करता है, लेकिन मेरा नहीं है? – Astronavigator

2

वैल्यू प्रकार कॉन्वर्सिस का समर्थन नहीं करते क्योंकि यह उनके आंतरिक प्रतिनिधित्व [1] को बदल देगा।

आप अजीब मामलों से बचना चाहते हैं मैं बजाय IsAssignableFrom का उपयोग कर की सिफारिश करेंगे:

public static bool IsCovariantIEnumerable(Type T1, Type T2) => T1.IsAssignableFrom(T2);

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