ध्यान देने वाली पहली बात यह है कि सी # आमतौर पर किसी संदर्भ प्रकार पर वर्चुअल कॉल करता है, भले ही विधि वर्चुअल नहीं है। ऐसा इसलिए है क्योंकि एक सी # नियम है कि एक शून्य संदर्भ पर एक विधि को कॉल करना अवैध है जो .NET नियम नहीं है (कच्चे सीआईएल में यदि आप एक शून्य संदर्भ पर एक विधि कहते हैं और वह विधि स्वयं किसी फ़ील्ड तक नहीं पहुंचती है या वर्चुअल विधि, यह ठीक काम करता है) और callvirt
का उपयोग उस नियम को लागू करने का एक सस्ता तरीका है।
सी # गैर आभासी उदाहरण के लिए call
बजाय callvirt
उत्पन्न होगा कुछ मामलों में जहां यह स्पष्ट है कि संदर्भ रिक्त नहीं है में कहता है। विशेष रूप से obj?.SomeMethod()
के साथ ?.
का अर्थ है कि एक नल-चेक पहले से ही हो रहा है, तो SomeMethod()
वर्चुअल नहीं है, इसे call
पर संकलित किया जाएगा। यह ?.
के साथ होता है क्योंकि ?.
संकलित करने के लिए कोड यह जांच कर सकता है जबकि यह if (obj != null){obj.SomeMethod();}
के साथ नहीं होता है क्योंकि .
संकलित कोड यह नहीं जानता है कि यह एक शून्य-जांच का पालन कर रहा है। शामिल तर्क बहुत स्थानीय है।
सीआईएल स्तर पर आभासी तरीकों के लिए वर्चुअल टेबल लुकअप को छोड़ना संभव है। इस प्रकार base
कॉल काम करता है; callvirt
की बजाय किसी विधि के कार्यान्वयन के आधार पर call
पर संकलित किया गया। निर्माण obj?.SomeMethod()
में विस्तार से जहां SomeMethod
आभासी और मुहरबंद था (चाहे व्यक्तिगत रूप से या obj
का प्रकार सील कर दिया गया था) तो यह सैद्धांतिक रूप से संभवतः call
को सबसे व्युत्पन्न प्रकार के कार्यान्वयन के रूप में संकलित करना संभव होगा। हालांकि कुछ अतिरिक्त चेक जो विशेष रूप से किए जाने की आवश्यकता है यह सुनिश्चित करने के लिए कि यह अभी भी सही तरीके से काम करता है यदि घोषित प्रकार और मुहरबंद प्रकार के बीच पदानुक्रम में कक्षाएं ओवरराइड जोड़ती हैं या हटाती हैं। ऑप्टिमाइज़ेशन सुरक्षित होने के लिए इसे पदानुक्रम के कुछ वैश्विक ज्ञान की आवश्यकता होगी (और आश्वासन है कि ज्ञान नहीं बदलेगा, जिसका मतलब है कि वर्तमान में असेंबली में सभी प्रकार के संकलन किए जा रहे हैं)। और लाभ छोटा है। और अभी भी अधिकांश कारणों के लिए उपलब्ध नहीं है क्योंकि callvirt
का उपयोग अधिकांश समय गैर-वर्चुअल कॉल पर भी किया जाता है।
मुझे नहीं लगता कि वहां कहीं भी है जहां sealed
संकलक कैसे कॉल उत्पन्न करता है, और यह निश्चित रूप से इसे अधिकांश समय प्रभावित नहीं कर रहा है।
जिटर अधिक ज्ञान लागू करने के लिए स्वतंत्र है, लेकिन यदि कोई भी बहुत छोटा हो रहा है तो फिर अंतर। मैं निश्चित रूप से उन वर्गों को चिह्नित करने की अनुशंसा करता हूं जिन्हें आप जानते हैं उन्हें sealed
के रूप में ओवरराइड नहीं किया जाएगा और यदि जिटर इसका उपयोग करता है तो यह बहुत अच्छा है, लेकिन मुख्य कारण यह है कि मैं अनुशंसा करता हूं कि यह प्रदर्शन नहीं बल्कि सहीता है। यदि आप कहीं ऐसी कक्षा को ओवरराइड करने का प्रयास करते हैं जिसे आपने sealed
पर चिह्नित किया था तो या तो ए। आपने अभी डिज़ाइन को थोड़ा बदल दिया है और आपको पता था कि आपको sealed
(.5 सेकेंड इसे हटाने के लिए काम करना होगा) या बी को हटा देना होगा। एक जगह में कुछ किया जो आपको यकीन था कि आप दूसरे में नहीं होंगे। पुनर्विचार का संक्षिप्त विराम होना अच्छा है।
यदि मैं कक्षा को सील कर देता हूं तो इसका मतलब यह है कि कक्षा पदानुक्रम में सभी आभासी तरीकों को भी सील कर दिया गया है?
उन्हें स्पष्ट रूप से चिह्नित किया गया है जैसा कि उन्हें स्पष्ट रूप से चिह्नित किया गया है।
स्रोत
2017-02-28 11:34:06
नहीं, विधि कॉल अभी भी वर्चुअल होगा। – InBetween
आप लगभग सही हैं - आपको विधि को 'मुहरबंद' के रूप में चिह्नित करने की आवश्यकता है, कक्षा नहीं। – Nat
@Nat लेकिन जैसा कि मैंने नीचे टिप्पणी की - यह आलेख कहता है कि कक्षा को सील किया जा सकता है http://codebetter.com/patricksmacchia/2008/01/05/rambling-on-the-sealed-keyword/ मेरे लिए चिह्नित करना आसान है कक्षा प्रत्येक वर्चुअल विधि के बजाय मुहरबंद। –