2016-09-21 10 views
5

के लिए काम नहीं कर रहा है, इसके साथ निहित ऑपरेटर मूल रूप से निम्न श्रेणी (उदाहरण C# creating an implicit conversion for generic class? पर पाया गया है)।जेनेरिक इंटरफ़ेस

class MyClass<T> 
{ 
    public MyClass(T val) 
    { 
    Value = val; 
    } 

    public T Value { get; set; } 

    public static implicit operator MyClass<T>(T someValue) 
    { 
    return new MyClass<T>(someValue); 
    } 

    public static implicit operator T(MyClass<T> myClassInstance) 
    { 
    return myClassInstance.Value; 
    } 
} 

एक कर सकता है

MyClass<IFoo> foo1 = new Foo(); 
MyClass<Foo> foo2 = new Foo(); 

//But not 
MyClass<IFoo> foo3 = (IFoo)new Foo(); 

असली मुद्दा तब होता है जब

void Bar(IFoo foo) 
{ 
    Bar2(foo); 
    //What should be the same as 
    Bar2<IFoo>(new MyClass<IFoo>(foo)); 
} 

void Bar2<T>(MyClass<T> myClass) 
{ 
    //Do stuff 
} 

की तरह कुछ करने के लिए मैं MyClass कैसे refactor सकता है तो यह वस्तुओं के साथ काम करने के लिए जब केवल संभव होगा की कोशिश कर रहा इंटरफेस ज्ञात है?

+0

मुझे समझ में नहीं आता कि आप वास्तव में इसके साथ क्या हासिल करने की कोशिश कर रहे हैं। MyClass हमेशा एक IFoo ऑब्जेक्ट (इंटरफेस और कार्यान्वयन) का उपयोग करता है या यह किसी और चीज का उपयोग कर सकता है? वैसे भी, यदि आप एक इंटरफ़ेस को पूर्ण रूप से परिवर्तित करने की कोशिश कर रहे हैं, तो सी # में असंभव है (जैसा कि @EricLippert पहले से ही कहा गया है) –

+0

एकाधिक IFoo कार्यान्वयन (Foo1, Foo2, .. FooN) होंगे। अन्य इंटरफेस बार भी हो सकते हैं (अन्य इंटरफेस अन्य) {बार 2 <अन्य इंटरफेस> (अन्य); } पाठ्यक्रम का सवाल वास्तविक समस्या का एक अलग संस्करण है। –

उत्तर

12

लघु जवाब:

उपयोगकर्ता-परिभाषित अंतर्निहित रूपांतरण इंटरफेस पर काम नहीं करते। इसे काम करने की कोशिश मत करो। अपनी टाइप सिस्टम समस्या के लिए एक और समाधान खोजें।

लांग जवाब:

यह सी # डिजाइन टीम के एक विचार निर्णय है। सिद्धांत यह है कि जब आप एक इंटरफ़ेस से जुड़े रूपांतरण कर रहे होते हैं तो आप संदर्भित पहचान को संरक्षित करना चाहते हैं; आप उस ऑब्जेक्ट के पहचान के बारे में पूछ रहे हैं जो इंटरफ़ेस लागू करता है, समान गुण बनाने वाले समान ऑब्जेक्ट को बनाने का प्रयास नहीं कर रहा है।

यहां बड़ा सिद्धांत यह है कि उपयोगकर्ता द्वारा परिभाषित रूपांतरण को अंतर्निहित रूपांतरण को प्रतिस्थापित नहीं करना चाहिए। लेकिन चूंकि लगभग किसी वर्ग को उप-वर्गीकृत किया जा सकता है, और वह सबक्लास किसी भी इंटरफ़ेस के बारे में केवल कार्यान्वित कर सकता है, स्थिर रूप से जानना बहुत मुश्किल है कि किसी दिए गए उपयोगकर्ता द्वारा परिभाषित रूपांतरण में एक अंतर्निहित रूपांतरण एक प्रतिस्थापित रूपांतरण को प्रतिस्थापित कर सकता है।

एफवाईआई यह विनिर्देश का एक विशेष रूप से मुश्किल बिट है, और सी # कंपाइलर में कुछ कीड़े हैं। मुझे संदेह है कि उपरोक्त आपके मामलों में से एक इन बग का लाभ उठाता है; तथ्य यह है कि असली दुनिया के कार्यक्रम हैं जो ऐसा करते हैं जो मुझे बग को ठीक करने से रोकता है।

बग ज्यादातर जेनरिक से पहले इस सुविधा के डिजाइन किए जाने का एक परिणाम हैं, और फिर जेनेरिकों ने कई अप्रत्याशित जटिलताओं को पेश करने के बाद पर्याप्त रूप से फिर से डिजाइन नहीं किया है।

विवरण के लिए, यहां मेरी व्यापक टिप्पणियां देखें, विशेष रूप से बिल्ट्स को डिलीवरी स्पेक विलोपन चिह्नित किया गया है जो इंटरफ़ेस रूपांतरणों के साथ समस्याओं का वर्णन करता है।

https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs

आप देख सकते हैं, इस फाइल को एक हजार लाइनों लंबे तुलना में कम है, और आधे टिप्पणी से शायद अधिक है। सावधानीपूर्वक शोध के सप्ताह और इन अर्थशास्त्रों को हल करने के लिए भाषा टीम के साथ कई चर्चाएं हुईं। एक बार जब आप एक कंपाइलर में गलती करते हैं, तो आपको इसे एक दशक बाद पूरी तरह से समझना पड़ता है, और उसके बाद इसे हमेशा के लिए स्थापित करना होता है ताकि ग्राहक को अपग्रेड पर नहीं तोड़ दिया जा सके। भाषा डिजाइनरों को कई ऑब्जेक्ट सबक हैं कि कैसे सी # ने विनिर्देश के इस अस्पष्ट हिस्से को गड़बड़ कर दिया।

मैं माइक्लास को कैसे दोबारा कर सकता हूं ताकि केवल इंटरफ़ेस ज्ञात होने पर ऑब्जेक्ट्स के साथ काम करना संभव हो?

कोशिश न करें।वास्तविक रनटाइम प्रकार के इंटरफ़ेस संदर्भ कास्ट करें और फिर वहां से इसके साथ काम करें। या निहित रूपांतरण के बजाए वांछित प्रकार का एक उदाहरण स्पष्ट रूप से बनाएं। निहित रूपांतरण और इंटरफेस के साथ गेम खेलने की कोशिश न करें; यह अच्छी तरह से काम नहीं करेगा।

+0

Foo1, Foo2, ..., FooN है। मुद्दा यह होगा कि MyClass की परवाह नहीं है क्योंकि बार() नहीं पता होगा। (भविष्य में फूक्स हो सकता है)। तो वास्तविक रन-टाइम प्रकार पर कास्टिंग एक विकल्प नहीं है। –

+0

वास्तव में वास्तव में। अगर मैं'void Bar (MyClass foo) लिखता हूं, तो मैं उस बिंदु पर किसी भी IFoo कार्यान्वयन (Foo1, Foo2, .., FooN, FooX) इंजेक्ट कर सकता हूं क्योंकि अंतर्निहित रूपांतरण मान्य होगा ... –

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