2010-09-23 8 views
23

आज मेरे साथ कुछ ऐसा हुआ जो मुझे मेरे सिर को खरोंच कर रहा है।Nullable <T> के मुक्केबाजी/अनबॉक्सिंग व्यवहार को कैसे संभव है?

Nullable<T> के किसी भी प्रकार को null पर असाइन किया जा सकता है। उदाहरण के लिए:

int? i = null; 

पहले तो मुझे नहीं देख सकता था कि यह कैसे संभव होगा किसी भी तरह Nullable<T> को object से एक अंतर्निहित रूपांतरण को परिभाषित करने के बिना:

public static implicit operator Nullable<T>(object box); 

लेकिन इसके बाद के संस्करण ऑपरेटर स्पष्ट रूप से मौजूद नहीं है, के रूप में अगर ऐसा किया तो निम्न भी कानूनी होने के लिए कम से कम संकलन समय पर (जो यह नहीं है) के लिए होता है:

int? i = new object(); 

तो मुझे लगता है कि पे महसूस किया rhaps Nullable<T> प्रकार इस तरह, कुछ मनमाने ढंग से संदर्भ प्रकार है कि instantiated कभी नहीं किया जा सकता है के लिए एक अंतर्निहित रूपांतरण निर्धारित कर सकते हैं:

public abstract class DummyBox 
{ 
    private DummyBox() 
    { } 
} 

public struct Nullable<T> where T : struct 
{ 
    public static implicit operator Nullable<T>(DummyBox box) 
    { 
     if (box == null) 
     { 
      return new Nullable<T>(); 
     } 

     // This should never be possible, as a DummyBox cannot be instantiated. 
     throw new InvalidCastException(); 
    } 
} 

बहरहाल, यह स्पष्ट नहीं होता कि आगे क्या घटित हुआ: अगर HasValue संपत्ति किसी के लिए false है , अगर HasValuetrue है,

int? i = new int?(); 
object x = i; // Now x is null. 

इसके अलावा तो मूल्य: Nullable<T> मूल्य है, तो उस मूल्य null के रूप में बॉक्सिंग की जाएगी के रूप में बॉक्सिंग हो जाएगा एक T बल्कि एक T? से:

int? i = 5; 
object x = i; // Now x is a boxed int, NOT a boxed Nullable<int>. 

लेकिन इस मतलब के लिए एक कस्टम अंतर्निहित रूपांतरण Nullable<T> से object लिए है कि वहाँ लगता है:

public static implicit operator object(Nullable<T> value); 

यह स्पष्ट रूप से मामला नहीं है object सभी प्रकार के लिए एक बेस क्लास है, और आधार-प्रकार से उपयोगकर्ता परिभाषित अंतर्निहित रूपांतरण अवैध हैं (साथ ही वे होना चाहिए)।

ऐसा लगता है कि object x = i;, i किसी अन्य मान प्रकार की तरह बॉक्स ताकि x.GetType()typeof(int?) के समान ही परिणाम हैं (बजाय फेंक एक NullReferenceException) चाहिए।

तो मैं थोड़ा और, यकीन है कि पर्याप्त चारों ओर खोदा, यह पता चला है इस व्यवहार Nullable<T> प्रकार, विशेष रूप से दोनों में C# और VB.NET विनिर्देशों परिभाषित है, और किसी भी उपयोगकर्ता परिभाषित struct (सी # में प्रतिलिपि प्रस्तुत करने योग्य नहीं के लिए विशिष्ट है) या Structure (वीबीएनईटी)।

यहां मैं अभी भी उलझन में हूं।

यह विशेष मुक्केबाजी और अनबॉक्सिंग व्यवहार हाथ से लागू करना असंभव प्रतीत होता है। यह केवल काम करता है क्योंकि सी # और वीबी.नेट दोनों Nullable<T> प्रकार के लिए विशेष उपचार देते हैं।

  1. नहीं यह सैद्धांतिक रूप से संभव है कि एक अलग CLI आधारित भाषा मौजूद हो सकता है जहां Nullable<T> इस विशेष उपचार नहीं दिया गया? और Nullable<T> प्रकार अलग-अलग भाषाओं में विभिन्न व्यवहार प्रदर्शित नहीं करेगा?

  2. सी # और वीबीएनईटी कैसे इस व्यवहार को प्राप्त करते हैं? क्या यह सीएलआर द्वारा समर्थित है? (यही है, CLR एक विशेष प्रकार के किसी भी तरह "ओवरराइड" जिस तरह से यह बॉक्सिंग है, भले ही C# और VB.NET खुद को यह निषेध अनुमति देता है?)

  3. है तो यह और भी संभव (सी # में या वीबीएनईटी) Nullable<T> को object के रूप में बॉक्स करने के लिए?

+2

यह जेआईटी कंपाइलर है जो व्यवहार को लागू करता है। यहां और अधिक: http://stackoverflow.com/questions/1583050/performance-surprise-with-as-and-nullable-types/3076525#3076525 –

+1

मुझे एहसास है कि मैं पार्टी के लिए 7 साल देर से हूं। लेकिन, मैं सुझाव देना चाहूंगा कि मेरे जैसे उत्सुक किसी भी अंतर्दृष्टि के लिए संदर्भ स्रोत भी पढ़ें। https://referencesource.microsoft.com/#mscorlib/system/nullable।सीएस, ffebe438fd9cbf0e – Licht

उत्तर

26

वहाँ चल रहा दो बातें हैं:

1) संकलक व्यवहार करता है "अशक्त" नहीं एक अशक्त संदर्भ के रूप में लेकिन मूल्य एक अशक्त के रूप में ... शून्य मान जो कुछ प्रकार के लिए इसकी आवश्यकता है में कनवर्ट करने के लिए। Nullable<T> के मामले में यह केवल वह मान है जो HasValue फ़ील्ड/संपत्ति के लिए गलत है। तो यदि आपके पास int? प्रकार का चर है, तो यह चर के मान के लिए null होना संभव है - आपको केवल null का अर्थ समझने की आवश्यकता है।

2) बॉक्सिंग नालीबल प्रकार सीएलआर द्वारा विशेष उपचार प्राप्त करते हैं। यह आपके दूसरे उदाहरण में प्रासंगिक है:

int? i = new int?(); 
    object x = i; 

संकलक गैर-व्यर्थ प्रकार मूल्यों के लिए अलग तरह किसी भी नल प्रकार मान बॉक्स होगा। यदि मान शून्य नहीं है, तो परिणाम मुक्केबाजी के समान ही गैर-शून्य प्रकार के मान के समान होगा - इसलिए int? वैल्यू 5 के साथ int के साथ वैल्यू 5 के साथ बॉक्सिंग हो जाता है - "शून्यता" खो गया। हालांकि, एक ऑब्जेक्ट बनाने के बजाए, एक शून्य प्रकार के शून्य मूल्य को केवल शून्य संदर्भ के लिए बॉक्स किया गया है।

यह समुदाय के अनुरोध पर सीएलआर v2 चक्र में देर से पेश किया गया था।

इसका मतलब है कि "बॉक्स किए गए शून्य-मूल्य-प्रकार मान" जैसी कोई चीज़ नहीं है।

+2

सामान्य रूप से स्पॉट - आईएल कोड देखकर, ऑब्जेक्ट x = मुझे बॉक्स निर्देश में परिवर्तित किया जाता है जो सीएलआर स्तर पर समर्थन दर्शाता है। – VinayC

+0

मुझे लगता है कि सीएलआर से विशेष उपचार प्राप्त करने के बारे में आपको क्या मतलब है: मैंने अभी एक त्वरित परीक्षण लिखा है और आईएल को रिफ्लेक्टर में देखा है और देखा है कि सी # कंपाइलर 'Nullable के मुक्केबाजी को हटाने के लिए कुछ भी विशेष नहीं दिखता है 'खुद लेकिन फिर यह अजीब बात नहीं है कि 'Nullable ' के मुक्केबाजी के प्रभाव को सी # और वीबी.नेट चश्मा में स्वतंत्र रूप से निर्दिष्ट किया गया है? क्या यह सीएलआई स्पेक में भी है, क्या आप जानते हैं? –

+0

@Dan: हाँ, यह सी # spec में है। मुझे नहीं पता कि यह वीबीएनईटी स्पेक में है या नहीं। सीएलआई स्पेक (ईसीएमए -335) में यह विभाजन 1 की धारा 8.2.4 में है। –

2

आप इसे अधिकार मिल गया: Nullable<T>, संकलक से विशेष उपचार हो जाता है में दोनों वीबी और सी #। इसलिए:

  1. हां। भाषा संकलक को विशेष मामले Nullable<T> की आवश्यकता होती है।
  2. कंपाइलर रिफैक्टर Nullable<T> का उपयोग करते हैं। ऑपरेटर सिर्फ वाक्य रचनात्मक चीनी हैं।
  3. मुझे नहीं पता कि मुझे पता है।
+0

तो आपके दूसरे उत्तर के जवाब में: सी # कंपाइलर (उदाहरण के लिए) 'ऑब्जेक्ट x = i;' जैसे कुछ ऑब्जेक्ट x = i.HasValue को दोबारा करना चाहिए? (ऑब्जेक्ट) i.Value: शून्य, 'क्या मैं सही हूँ? जिसका अर्थ है कि भाषा वास्तव में मानक मुक्केबाजी व्यवहार को पूरी तरह से अस्वीकार कर रही है (मुझे अभी एहसास हुआ है कि 'ऑब्जेक्ट x = (int?) 5; '' x' बॉक्स बॉक्स' int', * नहीं * 'Nullable ') बनाता है। दिलचस्प ... –

+0

आईएल को देखते हुए, सीएलआर को न्यूबल के लिए विशेष समर्थन है। अनुपालन बॉक्स निर्देश और सीएलआर चेक मान को यह निर्धारित करने के लिए उत्सर्जित करता है कि शून्य मान या बॉक्स वास्तविक मूल्य प्रकार मान को रेफरी करना है या नहीं। – VinayC

+0

'GetRandomNullable ' विधि से उत्पन्न आईएल को देखने से मैं सिर्फ खुद को परावर्तक में मारता हूं, ऐसा लगता है कि विनयसी सही है: मुझे लगता है कि सी # कंपाइलर वास्तव में मुक्केबाजी को दोबारा नहीं कर रहा है, जिसका मतलब है (मेरे लिए) विशेष उपचार वास्तव में * करता है * सीएलआर स्तर पर होता है। लेकिन अगर यह सच है, तो यह अजीब लगता है (मेरे लिए) कि व्यवहार भाषा विनिर्देशों में स्वयं परिभाषित किया जाएगा। कोई विचार? –

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