2012-09-07 11 views
7

एक दिलचस्प अजीबता मिली - सोचा कि कोई मदद करने में सक्षम हो सकता है।वीबी.नेट कंपाइलर कैसे चलने के लिए कौन सा एक्सटेंशन ओवरलोड चुनता है?

यह इस सवाल से नल प्रकार के साथ कुछ मज़ा से बाहर आया:

How to check if an object is nullable?

Option Strict On 

Module Test 
    ' Call this overload 1 
    <Extension()> 
    Function IsNullable(obj As ValueType) As Boolean 
    Return False 
    End Function 

    ' Call this overload 2 
    <Extension()> 
    Function IsNullable(Of T As {Structure})(obj As Nullable(Of T)) As Boolean 
    Return True 
    End Function 

    Sub Test() 
    ' a is an integer! 
    Dim a As Integer = 123 

    ' calling IsNullable as an extension method calls overload 1 and returns false 
    Dim result1 As Boolean = a.IsNullable() 

    ' calling IsNullable as method calls overload 2 and returns true 
    Dim result2 As Boolean = IsNullable(a) 

    ' why? surely the compiler should treat both those calls as equivalent 
    End Sub 
End Module 

मैं उम्मीद करेंगे कि IsNullable के दोनों कॉल माना जाएगा संकलक द्वारा एक ही है, लेकिन यह नहीं है मुकदमा। विस्तार विधि कॉल सामान्य विधि कॉल में एक अलग अधिभार का उपयोग करता है भले ही तर्क "ए" अपरिवर्तित है।

मेरा प्रश्न है क्यों? क्या कंपेलर दो कॉल के बीच अपना मन बदलता है?

FTR: हम दृश्य स्टूडियो 2010 का उपयोग कर रहे हैं, .NET फ़्रेमवर्क 4

+0

आपका प्रश्न वास्तव में वे एक, स्पष्ट "आप टेस्ट उप ही अधिभार में परिणाम होगा में IsNullable के दोनों कॉल इस्तेमाल किया जा रहा लगता होगा नहीं है एक अलग का उपयोग करें। " –

+0

पॉइंट लिया गया मैंने अपने कोड में कुछ टिप्पणियां जोड़ दी हैं। उम्मीद है कि यह चीजों को स्पष्ट करता है। –

उत्तर

0

मुझे लगता है कि यह एक बग, या कम से कम एक VB.NET "सुविधा" है। (मुझे यकीन नहीं है कि वीबी.नेट या सी # का क्या गलत है।)

मैंने LINQPad 4 में कोशिश की है (क्योंकि मुझे वह मशीन है जो मैं उपयोग कर रहा हूं) और सी # के लिए मुझे False मिला दोनों परिणामों के लिए, Nullable प्रकारों को छोड़कर, प्रत्येक मूल्य प्रकार और enum के लिए, निश्चित रूप से।

जबकि VB.NET के लिए मैं False और सभी मूल्य प्रकार और enums के लिए True, Nullable प्रकार के अलावा मिलता है, और ValueType और [Enum] जो लौट False, False क्योंकि आप एक ValueType? या [Enum]? नहीं हो सकता। Option Strict Off के साथ, Object देर से बाध्यकारी का कारण बनता है, और ओवरलोड लोड करने के लिए रनटाइम पर विफल रहता है, लेकिन दूसरा परिणाम False भी है क्योंकि आपके पास Object? नहीं हो सकता है।

पूर्णता के लिए, Nullable प्रकार True, True दोनों भाषाओं के लिए वापसी की वापसी के लिए।

तथ्य यह है कि सी # कुछ अलग कर रहा है (मान लीजिए कि मेरा परीक्षण सही है) सी # "बेहतर रूपांतरण" चेक का संदर्भ गलत है (या कम से कम गलत पढ़ा जा रहा है - उस सी # में ऐसा नहीं किया जा रहा है जिसे व्याख्या किया जा रहा है क्यों वीबी.नेट ऐसा कर रहा है जो यह कर रहा है)।

हालांकि, मैं सहमत हूं कि यह मुद्दा संभवतः Nullable(Of T) पर अंतर्निहित रूपांतरण से संबंधित है और किसी भी तरह से ValueType पर अंतर्निहित रूपांतरण के लिए उच्च प्राथमिकता है।

यहाँ मेरी LINQPad 4 "प्रश्न" (सी # कार्यक्रम) है:

void Main() 
{ 
    Test.test(); 
} 

// Define other methods and classes here 
static class Test 
{ 
    static bool IsNullable(this ValueType obj) 
    { 
     return false; 
    } 

    static bool IsNullable<T>(this T? obj) where T:struct 
    { 
     return true; 
    } 

    public static void test() 
    { 
     int x = 42; 

     bool result1 = x.IsNullable(); 
     bool result2 = IsNullable(x); 

     result1.Dump("result1"); 
     result2.Dump("result2"); 
    } 
} 
+0

बीटीडब्ल्यू किसी भी भाषा में 'ValueType?' का जिक्र करते समय त्रुटि नोट करें :-) –

+0

मुझे लगता है कि यह VB.NET 14/C# 6 (VS2015) के साथ नहीं बदला है। तो मुझे लगता है कि माइक्रोसॉफ्ट ने फैसला किया है कि यह एक विशेषता है कि दोनों भाषाएं यहां भिन्न हैं। (मैंने यह भी नोट किया है कि उपर्युक्त त्रुटि संदेशों का वीबी.नेट संस्करण अधिक जानकारीपूर्ण है, लेकिन दोनों अभी भी "हास्यास्पद" महसूस करते हैं।) –

+0

नहीं, अब मुझे यकीन है कि यह अभी भी एक सी # बग है: सी # एक 'IsNullable (यह int ओबीजे) 'अधिभार अगर इसे परिभाषित किया गया है (जैसा कि पाठ्यक्रम के वीबीएनईटी करता है)। (और न तो भाषा इसे संदिग्ध कहती है जब 'टी? 'अधिभार अभी भी उपलब्ध है।) –

2

अधिभार 2 केवल एक विस्तार के रूप में काम करेंगे पर स्पष्ट रूप से (टी के) के Nullable परिभाषित किया। उदाहरण के लिए:

Dim y As New Nullable(Of Integer) 
    y.IsNullable() 

इसका कारण यह है विस्तार तरीकों प्रकार (या एक आधार प्रकार), जो इस मामले में (टी का) Nullable है विस्तार। कॉलिंग a.IsNullable() कभी अधिभार नहीं कॉल करेगा 2. यह पता लगाने का एक आसान हिस्सा है। इसका मतलब यह है कि असली सवाल यह है कि ओवरलोड लोड के बजाय अधिभार 2 को मानक अधिभारित विधि कॉल के रूप में क्यों बुलाया जाएगा।

सीएलआर निर्धारित करेगा कि "Better Conversion" चेक करके कौन सा अधिभार उपयोग करना है, जहां यह अधिभारित रूप से अधिभारित विधियों में परिभाषित पैरामीटर (ओं) के प्रकार में पारित मान (ओं) को परिवर्तित करता है और फिर नीचे जाता है उपयोग करने के लिए सबसे अच्छी विधि निर्धारित करने के लिए नियमों की चेकलिस्ट।

MSDN बेहतर रूपांतरण अनुच्छेद से:

एस टी 1 है, तो सी 1 बेहतर रूपांतरण है।

यदि एस टी 2 है, तो सी 2 बेहतर रूपांतरण है।

Puting दृश्य स्टूडियो इच्छा में इस कोड को आप पता चलता है कि अधिभार 2 बेहतर रूपांतरण क्योंकि पूर्णांक एक (एस) परोक्ष परिवर्तित Nullable (पूर्णांक के) एक (टी 2) का संस्करण है।

' a is an integer! 
    Dim a As Integer = 123 

    Dim objValueType As ValueType = 123 'Or CType(a, ValueType) 
    Dim objNullable As Nullable(Of Integer) = 123 'Or CType(a, Nullable(Of Integer)) 

    'Oh No, a compiler error for implicit conversion done for overload 1! 
    Dim bolValueTypeConversionIsBetter As Boolean = (objValueType = a) 

    'No error as long as Option Strict is off and it will equal True. 
    Dim bolNullableConversionIsBetter As Boolean = (objNullable = a) 
+0

यह सीएलआर निर्धारित करने वाला नहीं है, यह वीबी.नेट कंपाइलर है, और आपका लिंक सी # संस्करण के लिए है। फिर भी यह [समकक्ष वीबी.नेट दस्तावेज] (http://msdn.microsoft.com/en-us/library/aa712031.aspx) से अधिक पठनीय हो सकता है। –

+0

@ मार्कहर्ड, कंपाइलर पर अच्छा बिंदु। उस स्पष्टीकरण के लिए धन्यवाद। – N0Alias

+0

बीटीडब्ल्यू 'वैल्यू टाइप' की तुलना में समस्या यह है कि 'वैल्यू टाइप' के लिए परिभाषित '==' नहीं है, न कि अंतर्निहित रूपांतरण नहीं किया जा सकता है। –

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