2010-03-09 15 views
18

हममें से वे जो वीबी/VB.NET में काम किया है इस abomination के समान कोड को देखा है:क्या वीबी.नेट "अगर" ऑपरेटर मुक्केबाजी का कारण बनता है?

Dim name As String = IIf(obj Is Nothing, "", obj.Name) 

मैं कहता हूँ तीन सरल कारणों के लिए "abomination":

  1. IIf एक है फ़ंक्शन, जिनके पैरामीटर का मूल्यांकन किया जाता है; इसलिए यदि obj उपर्युक्त कॉल में कुछ भी नहीं है तो NullReferenceException फेंक दिया जाएगा। यह किसी ऐसे व्यक्ति के लिए अप्रत्याशित व्यवहार है जो सी # जैसी भाषाओं में लघु-सर्किट टर्नरी ऑपरेटरों के आदी है।
  2. क्योंकिIIf एक फ़ंक्शन है, इस प्रकार यह फ़ंक्शन कॉल के ओवरहेड को घुमाता है। फिर भी, हालांकि यह एक बड़ा सौदा नहीं है, यह किसी ऐसे व्यक्ति के लिए सही नहीं लगता है जो भाषा के लिए अंतर्निहित एक टर्नरी ऑपरेशन के रूप में व्यवहार करने की अपेक्षा करता है।
  3. IIf गैर सामान्य है और इसलिए प्रकार Object है, जो निम्नलिखित कॉल बॉक्स (मेरा मानना ​​है कि) तीन पूर्णांकों की कुल इसका मतलब के मापदंडों स्वीकार करता है:

    ' boxes 2nd and 3rd arguments as well as return value '
    Dim value As Integer = IIf(condition, 1, -1)

अब, वीबीएनईटी के कुछ और हालिया संस्करण में (मुझे यकीन नहीं है कि संख्या क्या है), If ऑपरेटर पेश किया गया था, जो IIf फ़ंक्शन के समान ही काम करता है लेकिन (जैसा कि मैं इसे समझता हूं) उसी शोर के बिना tcomings। ऐसा कहने के लिए, शॉर्ट-सर्किटिंग प्रदान करता है और एक इंट्रिनस्टिक वीबी ऑपरेशन है। हालांकि, मुझे अंतिम भाग के बारे में निश्चित नहीं है। MSDN documentation यह इंगित नहीं करता है कि If इसके तर्कों को बक्से या नहीं। क्या कोई जानता है?

+0

+1 यह प्रश्न मजेदार था! –

उत्तर

12

मुख्य बात यह है कि आपने एक कार्य के बजाय ऑपरेटर के रूप में सही ढंग से नए If की पहचान की है। यह टाइपएफ़ भी है और इसलिए मुक्केबाजी की आवश्यकता नहीं है, और सशर्त/टर्नरी/सीधी सीधी मैपिंग है? सी में ऑपरेटर/C++/सी #/जावा/आदि

यहां तक ​​कि नए ऑपरेटर के बिना, तो आप इस कोड के साथ VB.Net में कुछ सुधार हो सकता है:

Public Shared Function IIf(Of T)(ByVal Expression As Boolean, ByVal TruePart As T, ByVal FalsePart As T) As T 
    If Expression Then Return TruePart Else Return FalsePart 
End Function 
+0

मैंने वीबी.नेट टीम (कुछ भूल गए) पर कुछ डेवलपर के ब्लॉग में देखा कि उन्होंने ऐसा करने पर विचार किया था, वास्तव में - 'IIf' का एक सामान्य संस्करण प्रदान करना।मुझे खुशी है कि वे जिस मार्ग से गए थे, वे गए थे, क्योंकि जेनेरिक संस्करण मुक्केबाजी के मुद्दे को ठीक करेगा, लेकिन फिर भी शॉर्ट सर्किटिंग प्रदान नहीं करेगा (या फिर यह एक सामान्य विधि के रूप में छिपी हुई एक छोटी सर्किट वाली आंतरिक भाषा सुविधा के लिए बहुत भ्रमित होगा)। –

11

जोएल मुझे एक जवाब से हरा दिया, लेकिन यहाँ एक नमूना कार्यक्रम और जेनरेटेड आईएल है जो दर्शाता है कि अगर() मुक्केबाजी के बिना आईएल के अंतर्निहित टर्नरी ऑपरेटर से गुज़रता है।

Public Class Test 
    Public Sub New() 
     Dim rnd = New Random() 
     Dim result As Integer = If(rnd.Next(1000) < 500, 1, -1) 
     Console.WriteLine(result) 
    End Sub 
End Class 

जैसा कि आप देख सकते हैं कि आईएल में कोई 'बॉक्स' कथन नहीं है।

.method public specialname rtspecialname instance void .ctor() cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] int32 result, 
     [1] class [mscorlib]System.Random rnd) 
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call instance void [mscorlib]System.Object::.ctor() 
    L_0007: nop 
    L_0008: newobj instance void [mscorlib]System.Random::.ctor() 
    L_000d: stloc.1 
    L_000e: ldloc.1 
    L_000f: ldc.i4 0x3e8 
    L_0014: callvirt instance int32 [mscorlib]System.Random::Next(int32) 
    L_0019: ldc.i4 500 
    L_001e: blt.s L_0023 
    L_0020: ldc.i4.m1 
    L_0021: br.s L_0024 
    L_0023: ldc.i4.1 
    L_0024: stloc.0 
    L_0025: ldloc.0 
    L_0026: call void [mscorlib]System.Console::WriteLine(int32) 
    L_002b: nop 
    L_002c: nop 
    L_002d: ret 
} 

उसी कार्यक्रम को देखते हुए, पुराने IIF() फ़ंक्शन का उपयोग करके, निम्नलिखित आईएल का उत्पादन होता है। आप दोनों मुक्केबाजी, और फ़ंक्शन कॉल ओवरहेड देख सकते हैं:

.method public specialname rtspecialname instance void .ctor() cil managed 
{ 
    .maxstack 3 
    .locals init (
     [0] int32 result, 
     [1] class [mscorlib]System.Random rnd) 
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call instance void [mscorlib]System.Object::.ctor() 
    L_0007: nop 
    L_0008: newobj instance void [mscorlib]System.Random::.ctor() 
    L_000d: stloc.1 
    L_000e: ldloc.1 
    L_000f: ldc.i4 0x3e8 
    L_0014: callvirt instance int32 [mscorlib]System.Random::Next(int32) 
    L_0019: ldc.i4 500 
    L_001e: clt 
    L_0020: ldc.i4.1 
    L_0021: box int32 
    L_0026: ldc.i4.m1 
    L_0027: box int32 
    L_002c: call object [Microsoft.VisualBasic]Microsoft.VisualBasic.Interaction::IIf(bool, object, object) 
    L_0031: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToInteger(object) 
    L_0036: stloc.0 
    L_0037: ldloc.0 
    L_0038: call void [mscorlib]System.Console::WriteLine(int32) 
    L_003d: nop 
    L_003e: nop 
    L_003f: ret 
} 
+0

बहुत बढ़िया जवाब। धन्यवाद! –

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