मुझे यह जानकर उत्सुकता है कि यह क्यों हो रहा है।सी # कंपाइलर GetType() विधि कॉल के लिए कॉलवर्ट निर्देश उत्सर्जित क्यों कर रहा है?
using System;
class Program
{
static void Main()
{
Object o = new Object();
o.GetType();
// L_0001: newobj instance void [mscorlib]System.Object::.ctor()
// L_0006: stloc.0
// L_0007: ldloc.0
// L_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
new Object().GetType();
// L_000e: newobj instance void [mscorlib]System.Object::.ctor()
// L_0013: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
}
}
क्यों संकलक प्रथम खंड के लिए एक callvirt
लेकिन दूसरे खंड के लिए एक call
फेंकना था: कृपया नीचे दिए गए कोड उदाहरण और इसी आईएल कि प्रत्येक अनुभाग के नीचे टिप्पणी में उत्सर्जित किया गया था पढ़ा है? क्या कोई कारण है कि संकलक कभी गैर-आभासी विधि के लिए callvirt
निर्देश उत्सर्जित करेगा? और यदि ऐसे मामले हैं जिनमें संकलक गैर-वर्चुअल विधि के लिए callvirt
उत्सर्जित करेगा, तो यह टाइप-सुरक्षा के लिए समस्याएं पैदा करता है?
बहुत अच्छा प्रश्न ... मुझे मेरी पुस्तकों के लिए बाहर तक पहुँचने बनाया है। – Gishu
सारांश: केस (1) आभासी विधि का आह्वान करें: कॉलवर्ट उत्पन्न करें। केस (2) निरर्थक रिसीवर पर इंस्टेंस विधि का आह्वान करें: सस्ते नल चेक प्राप्त करने के लिए कॉलवर्ट उत्पन्न करें - हाँ, यह टाइपएफ़ है। केस (3) ज्ञात गैर-शून्य रिसीवर पर इंस्टेंस विधि का आह्वान करें: _avoid_ null check पर कॉल उत्पन्न करें। आपका पहला उदाहरण श्रेणी (2) में आता है, आपका दूसरा उदाहरण श्रेणी (3) में आता है। (कंपाइलर जानता है कि नया कभी वापस नहीं लौटाता है और इसलिए फिर से जांचने की आवश्यकता नहीं है।) –
धन्यवाद एरिक, शून्य जांच बहुत समझ में आता है। आपकी टिप्पणी प्लस गिशू का जवाब चीजों को और स्पष्ट बनाता है! :) –