2011-07-15 17 views
14

अगर मैं एक प्रकार पैरामीटर बाधा new() है:"जहां टी: नया()" दिया गया है, "नया टी()" एक्टिवेटर का उपयोग करता है। आंतरिक प्रवेश करें?

void Foo<T>() where T : new() 
{ 
    var t = new T(); 
} 

यह सही है कि new T() आंतरिक Activator.CreateInstance विधि (अर्थात प्रतिबिंब) का प्रयोग करेंगे?

+2

क्या इससे कोई फर्क पड़ता है? – Oded

+6

@ ओडेड यदि आप उस वातावरण को बेहतर ढंग से समझने की कोशिश कर रहे हैं जिसमें आप प्रोग्रामिंग कर रहे हैं, तो हाँ - इससे कोई फर्क नहीं पड़ता! :-) – Justin

+1

@ क्रैगेन: ildasm, monodis – sehe

उत्तर

11

हाँ, यह सच है। संपादित करें 2: यहां और कैसे एक अच्छा स्पष्टीकरण दिया गया है।

http://www.simple-talk.com/community/blogs/simonc/archive/2010/11/17/95700.aspx

सत्यापन मैं संकलित निम्न विधि के लिए

:

public static T Create<T>() where T: new() { 
    return new T(); 
} 

और जब .NET 3.5 SP1 में सी # संकलक के साथ संकलित इस उत्पन्न आईएल है:

.method public hidebysig static !!T Create<.ctor T>() cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] !!T local, 
     [1] !!T local2) 
    L_0000: ldloca.s local 
    L_0002: initobj !!T 
    L_0008: ldloc.0 
    L_0009: box !!T 
    L_000e: brfalse.s L_001a 
    L_0010: ldloca.s local2 
    L_0012: initobj !!T 
    L_0018: ldloc.1 
    L_0019: ret 
    L_001a: call !!0 [mscorlib]System.Activator::CreateInstance<!!T>() 
    L_001f: ret 
} 

संपादित करें: सी # 4 कंपाइलर थोड़ा अलग बनाता है, लेकिन इसी तरह, कोड:

.method public hidebysig static !!T Create<.ctor T>() cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] !!T CS$1$0000, 
     [1] !!T CS$0$0001) 
    L_0000: nop 
    L_0001: ldloca.s CS$0$0001 
    L_0003: initobj !!T 
    L_0009: ldloc.1 
    L_000a: box !!T 
    L_000f: brfalse.s L_001c 
    L_0011: ldloca.s CS$0$0001 
    L_0013: initobj !!T 
    L_0019: ldloc.1 
    L_001a: br.s L_0021 
    L_001c: call !!0 [mscorlib]System.Activator::CreateInstance<!!T>() 
    L_0021: stloc.0 
    L_0022: br.s L_0024 
    L_0024: ldloc.0 
    L_0025: ret 
} 

एक मान प्रकार यह उत्प्रेरक का उपयोग नहीं करता लेकिन सिर्फ default(T) मान देता है के मामले में, अन्यथा यह Activator.CreateInstance विधि invokes।

+0

@ जेसन: 'initobj' को परिभाषित किया गया है "मान प्रकार के प्रत्येक फ़ील्ड को एक निर्दिष्ट पते पर एक शून्य संदर्भ या उपयुक्त आदिम प्रकार के 0 में प्रारंभ करता है। ... न्यूबोज के विपरीत, initobj कन्स्ट्रक्टर विधि को कॉल नहीं करता है। Initobj मूल्य प्रकारों को शुरू करने के लिए है, जबकि ऑब्जेक्ट का उपयोग ऑब्जेक्ट आवंटित करने और प्रारंभ करने के लिए किया जाता है। " कोई संकेत नहीं है कि यह संदर्भ प्रकार के डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल करता है।मुझे लगता है कि यह 'डिफ़ॉल्ट (टी)' – CodesInChaos

+0

@CodeInChaos के बराबर है: मैंने पहले ही मेरी टिप्पणी हटा दी है। मैंने भूल की। – jason

+1

ठीक है, तो बड़ा सवाल यह है कि क्यों। संकलक सिर्फ 'newobj' निर्देश उत्सर्जित क्यों नहीं कर रहा है? – jason

1

हां। यह संदर्भ प्रकार के लिए करता है।

अगली रिलीज संकलित कोड पर ILSpy का उपयोग करना:

public static void DoWork<T>() where T: new() 
    { 
     T t = new T(); 
     Console.WriteLine(t.ToString()); 
    } 

झुकेंगे

.method public hidebysig 
    instance void DoWork<.ctor T>() cil managed 
{ 
    // Method begins at RVA 0x2064 
    // Code size 52 (0x34) 
    .maxstack 2 
    .locals init (
     [0] !!T t, 
     [1] !!T CS$0$0000, 
     [2] !!T CS$0$0001 
    ) 

    IL_0000: ldloca.s CS$0$0000 
    IL_0002: initobj !!T 
    IL_0008: ldloc.1 
    IL_0009: box !!T 
    IL_000e: brfalse.s IL_001b 

    IL_0010: ldloca.s CS$0$0001 
    IL_0012: initobj !!T 
    IL_0018: ldloc.2 
    IL_0019: br.s IL_0020 

    IL_001b: call !!0 [mscorlib]System.Activator::CreateInstance<!!T>() 

    IL_0020: stloc.0 
    IL_0021: ldloca.s t 
    IL_0023: constrained. !!T 
    IL_0029: callvirt instance string [mscorlib]System.Object::ToString() 
    IL_002e: call void [mscorlib]System.Console::WriteLine(string) 
    IL_0033: ret 
} // end of method Program::DoWork 

या सी # में:

public void DoWork<T>() where T : new() 
{ 
    T t = (default(T) == null) ? Activator.CreateInstance<T>() : default(T); 
    Console.WriteLine(t.ToString()); 
} 

JIT प्रत्येक अलग मूल्य के लिए अलग संकलित निर्देश पैदा करेगा प्रकार पैरामीटर पारित किया गया है, लेकिन संदर्भ प्रकारों के लिए एक ही निर्देश का उपयोग करेगा - वह एनसी एक्टिवेटर। क्रिएट इंस्टेंस()

+1

"वैल्यू प्रकार" के लिए भी सही है । 'पुस्तक के पृष्ठ 544/अध्याय 11 देखें- सी # प्रोग्रामिंग भाषा - तीसरा संस्करण'। –