2012-01-19 11 views
18

सी # 4, कॉलर्स को COM इंटरफ़ेस को रेफ पैरामीटर द्वारा तर्क के सामने रेफरी कीवर्ड को छोड़ने की अनुमति दें।सी # कंपाइलर बग या सामान्य COM विषमता? COM इंटरऑप को सरल बनाने के लिए

मुझे आज यह देखकर आश्चर्य हुआ कि यह COM इंटरफेस को विस्तारित करने वाले एक्सटेंशन विधियों पर भी लागू होता है। निम्नलिखित देखें, संकलित करें, कोड:

using System; 
using System.Runtime.InteropServices; 

[ComImport, Guid ("cb4ac859-0589-483e-934d-b27845d5fe74")] 
interface IFoo { 
} 

static class Program { 

    public static void Bar (this IFoo self, ref Guid id) 
    { 
     id = Guid.NewGuid(); 
    } 

    static void Main() 
    { 
     Foo (null); 
    } 

    static void Foo (IFoo o) 
    { 
     Guid g = Guid.NewGuid(); 
     Console.WriteLine (g); 

     // note that g is passed as is, and not as ref g  
     o.Bar (g); 

     Console.WriteLine (g); 
    } 
} 

मुझे इस व्यवहार को समझाने के लिए कल्पना में कुछ भी नहीं मिला।

मेरी भावना COM इंटरफ़ेस के बाहर कोड होगा, भले ही यह एक COM इंटरफ़ेस को विस्तारित करने वाली एक विस्तार विधि है, नियमित सी # नियमों का पालन करना चाहिए, और रेफरी कीवर्ड के उपयोग को लागू करना चाहिए। इसलिए मैंने bug on connect दायर किया। ऐसा नहीं है कि मुझे लगता है कि यह तय किया जाएगा, भले ही इसे एक बग के रूप में माना जाता है, फिर भी इस पर भरोसा करने वाला कोड पहले से ही है।

बग? एक बग नहीं है?

+3

बहुत दिलचस्प। 4.0 spec यहां संदिग्ध प्रतीत होता है।यह कहता है कि यह एक COM प्रकार (धारा 22 + 22.1) के तरीकों पर लागू होता है। लेकिन मुझे कुछ भी नहीं मिला जो स्पष्ट रूप से कहता है या नहीं कहता कि एक विस्तार विधि को इस तरह से एक प्रकार का हिस्सा माना जाता है। मेरा अनुमान है कि यह एक बग है। मुझे यकीन है कि एरिक जल्द ही स्पष्टीकरण के साथ होगा। – JaredPar

+11

यह सुनिश्चित है कि एक बग की तरह लगता है। बर्फ पर ठंडी बारिश के कारण आज भी मेरी बस चल रही नहीं है, और इसलिए मैं कार्यालय से दूर हूं। मैं अगले हफ्ते इसे देख लूंगा। कनेक्ट पर समस्या दर्ज करने के लिए धन्यवाद! –

उत्तर

2

मुझे नहीं लगता कि यह एक बग है; जैसा कि आप कहते हैं, यह "COM voodoo" जैसा दिखता है।

private static void Foo(IFoo o) 
{ 
    ... 
    Guid g = Guid.NewGuid(); 
    Guid <>r__ComRefCallLocal0 = g; 
    Bar(o, ref <>r__ComRefCallLocal0); 
    ... 
} 

सी # चाल से भरा वास्तव में है: हुड के अंतर्गत, सी # संकलक कुछ सही वास्तव में यह है कि, इस तरह का उत्सर्जन करता है। आप IFoo के लिए एक विधि, उदाहरण के लिए इस तरह,

[ComImport, Guid("cb4ac859-0589-483e-934d-b27845d5fe74")] 
interface IFoo 
{ 
    void Test([Optional] ref object test); 
} 

जोड़ देते हैं तो आप, फिर से, सी # 4 में इस घोषणा करने के लिए सक्षम हो जाएगा:

static void Foo(IFoo o) 
{ 
    Guid g = Guid.NewGuid(); 
    o.Test(g); 
} 

बेशक, क्योंकि यह सब केवल काम करता है सीएससी .EXE को ComImport विशेषता का अंतरंग ज्ञान है। मौजूदा COM इंटरफेस के साथ आसानी से इंटरऑप करने में सक्षम होने के लिए इन नए जादू इंटरऑप चाल को सी # 4.0 में जोड़ा गया था। खैर, माइक्रोसॉफ्ट ऑफिस इंटरफेस और विधियों के लिए ज्यादातर, और विशेष रूप से भयानक 'रेफ लापता' पैरामीटर की सेनाएं :-)

मुझे नहीं लगता कि यह कहीं भी पूरी तरह से निर्दिष्ट है। यह सब कुछ है जो सी # 4 विनिर्देशन कहना है:

17.5 इंटरऑपरेशन के लिए विशेषताएं नोट: यह अनुभाग केवल सी # के माइक्रोसॉफ्ट .NET कार्यान्वयन पर लागू है। 17.5.1 COM और Win32 घटकों के साथ इंटरैक्शन .NET रन-टाइम बड़ी संख्या में विशेषताओं को प्रदान करता है जो सी # प्रोग्राम को को COM और Win32 DLL का उपयोग करके लिखे गए घटकों के साथ इंटरऑपरेट करने में सक्षम बनाता है। उदाहरण के लिए, DllImport विशेषता का उपयोग स्थिर बाहरी विधि पर किया जा सकता है यह इंगित करने के लिए कि विधि का कार्यान्वयन Win32 DLL में पाया जाना है। ये गुण सिस्टम में पाए जाते हैं। रनटाइम.इंटरोप सेवा नामस्थान, और इन विशेषताओं के लिए विस्तृत दस्तावेज .NET रनटाइम दस्तावेज़ों में पाया जाता है।

और यहाँ MSDN पर कुछ पृष्ठ हैं:

+2

साइमन, मुझे पता है कि कंपाइलर उत्सर्जन वैध है। मुझे यह भी पता है कि COM इंटरफ़ेस विधि की कॉल साइटें रेफ पैरामीटर द्वारा तर्कों के लिए रेफरी को छोड़ सकती हैं, लेकिन यह सवाल नहीं है। प्रश्न यह जानना है कि क्या यह एक्सटेंशन विधियों पर लागू होता है, क्योंकि यह spec में निर्दिष्ट नहीं है। –

+0

यह स्पष्ट नहीं है कि आप क्या जानते हैं और सवाल से नहीं जानते हैं। मैंने "बग या बग नहीं" का जवाब देने की कोशिश की। मेरा मानना ​​है कि यह * बग * नहीं है क्योंकि यह सी # के माइक्रोसॉफ्ट .NET कार्यान्वयन है, इसलिए कार्यान्वयन और समर्थित परिदृश्य वही हैं जो माइक्रोसॉफ्ट ने तय किया है कि यह होना चाहिए। –

+0

@ सिमोन मॉरीयर, इसका मतलब यह होगा कि सी # में कभी भी कोई भी बग नहीं हो सकती है, यह बकवास है। सी # कंपाइलर सी # विनिर्देश द्वारा शासित है। यदि संकलक और विनिर्देश संघर्ष में हैं, तो इसका मतलब है कि एक बग है। यह कंपाइलर में या विनिर्देश में एक बग हो सकता है और यह जानबूझकर भी हो सकता है, लेकिन यह निश्चित रूप से एक बग है। – svick

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