2012-10-15 11 views
5

तो निम्न विधि है पर जाँच:प्रकार Nullable <int>

static void DoSomethingWithTwoNullables(Nullable<int> a, Nullable<int> b) 
{ 
    Console.WriteLine("Param a is Nullable<int>: " + (a is Nullable<int>)); 
    Console.WriteLine("Param a is int   : " + (a is int)); 
    Console.WriteLine("Param b is Nullable<int>: " + (b is Nullable<int>)); 
    Console.WriteLine("Param b is int   : " + (b is int)); 
} 

जब मैं एक पैरामीटर के रूप अशक्त के साथ इस विधि कॉल, प्रकार की जांच इस पैरामीटर के लिए झूठी देता है। उदाहरण के लिए इस कोड को

DoSomethingWithTwoNullables(5, new Nullable<int>()); 

इस उत्पादन में परिणाम:

Param a is Nullable<int>: True 
Param a is int   : True 
Param b is Nullable<int>: False 
Param b is int   : False 

जब एक Nullable का उपयोग करने और अशक्त गुजर वहाँ प्रकार की जानकारी को बचाने के लिये कोई तरीका है? मुझे पता है कि इस उदाहरण में प्रकार की जांच बेकार है, लेकिन यह समस्या को दर्शाती है। मेरी प्रोजेक्ट में, मैं पैरामीटर को दूसरी विधि में पास करता हूं जो params object[] सरणी लेता है और ऑब्जेक्ट्स के प्रकार की पहचान करने का प्रयास करता है। इस विधि को Nullable<int> और Nullable<long> के लिए अलग-अलग चीजें करने की आवश्यकता है।

उत्तर

5

सीधे अंतर्निहित समस्या पर जा रहे हैं, नहीं, आप यह नहीं कर सकते हैं। एक शून्य Nullable<int> में बिल्कुल शून्य बॉक्स Nullable<long>, या वास्तव में एक 'सामान्य' शून्य के रूप में समान बॉक्सिंग प्रतिनिधित्व है। यह कहने का कोई तरीका नहीं है कि यह किस प्रकार का 'शून्य' है, क्योंकि इसके अंतर्निहित प्रतिनिधित्व केवल सभी शून्य हैं। अधिक जानकारी के लिए Boxing Nullable Types देखें।

+0

क्योंकि बी को पहले 'int' के लिए बॉक्स किया गया है जिसके परिणामस्वरूप शून्य संदर्भ होता है। – usr

+0

संभवतः आप इसका परीक्षण करने के लिए {} पकड़ {} का प्रयास कर सकते हैं, इसलिए पता लगाने का एक तरीका है। मैं प्रतिबिंब का उपयोग कर शर्त लगाता हूं कि आप इसे एक कदम आगे ले सकते हैं और इसे पॉलिश कर सकते हैं। हो सकता है कि एक नया उदाहरण शुरू करें, जिसे इसे एक डिफ़ॉल्ट मान देना चाहिए, और 'typeof (variable.value)' करना चाहिए? – NibblyPig

+0

@ एसएलसी: आप नहीं कर सकते। यह प्रकार की जानकारी के बिना सिर्फ एक शून्य संदर्भ है। – usr

0

दुर्भाग्यवश, null किसी विशिष्ट स्मृति स्थान को इंगित नहीं करता है, और इस प्रकार कोई मेटाडेटा नहीं है जिसे आप प्रकार को देखने के लिए इसके साथ जोड़ सकते हैं। इस प्रकार, आप चर के बारे में कोई अतिरिक्त जानकारी प्राप्त नहीं कर सकते हैं।

3

अवधारणात्मक रूप से, new Nullable<int>null है।

अगर हम सामान्य, Nullable<T> के बारे में भूल जाते हैं:

string s = null; 
bool b = s is string; 

हम false मिलता है। falsenull मान पर एक प्रकार की जांच के लिए मूल्य है।

+1

क्या होगा अगर उसने 'बी = 3;' किया? यदि यह एक स्ट्रिंग है तो आपको एक त्रुटि मिलेगी, लेकिन अगर यह एक int या nullable int था तो आपको कोई त्रुटि नहीं मिलेगी? – NibblyPig

1

आप इसे प्राप्त करने के लिए प्रतिबिंब का उपयोग करने का प्रयास कर सकते हैं। Relevant article here.

+1

आप प्रतिबिंब का उपयोग नहीं कर सकते हैं। एक शून्य संदर्भ पर 'GetType() 'को कॉल करने से' NullReferenceException' फेंक देगा। शून्य संदर्भ से जुड़े कोई प्रकार नहीं है। लिंक किया गया लेख प्रकारों पर आधारित है और ऑब्जेक्ट्स के संदर्भ नहीं है (जो इस मामले में शून्य हो सकता है)। –

+0

@ मार्टिन सही है। –

0

जब तक कि मैं इस प्रश्न को गलत समझ नहीं पा रहा हूं, आप GetType() का उपयोग कर प्रकार प्राप्त कर सकते हैं। उदाहरण के लिए,

int? myNullableInt = null; 
Console.WriteLine(myNullableInt.GetValueOrDefault().GetType()); 

तो myNullableInt रिक्त है, तो डिफ़ॉल्ट मान लौटा दी जाएगी। इस लौटाए गए मूल्य के प्रकार की जांच करें और, इस मामले में, यह System.Int32 वापस कर देगा। आप प्रासंगिक कार्रवाई करने के लिए If..else/Switch लौटाए गए प्रकार पर जांच कर सकते हैं।

+0

या आप केवल 'Nullable.GetUnderlyingType() ' – phoog

+0

या वह कॉल कर सकते हैं। किसी भी तरह से, इस प्रश्न में आवश्यक जानकारी प्राप्त करना संभव लगता है। – keyboardP

+0

समस्या यह है कि मुझे नहीं पता कि दी गई वस्तु एक शून्य है या नहीं। यह एक स्ट्रिंग या सादा int भी हो सकता है। मैंने सोचा कि मैं इस जानकारी को प्राप्त करने के लिए टाइप चेक का उपयोग कर सकता हूं। लेकिन ऐसा लगता है कि यह मामला नहीं है। –

0

आप ऐसा नहीं कर सकते (int?Nullable<int> के समान है), और न ही आप करना चाहते हैं चाहिए। चूंकि Nullable<T> एक स्ट्रक्चर है, इस प्रकार के के मूल्य-प्रकार चर सभी संकलन समय पर आपको आवश्यक सभी प्रकार की जानकारी है। बस typeof ऑपरेटर का उपयोग करें।

दूसरी ओर, आपके पास एक नालीबल उदाहरण हो सकता है जिसका प्रकार आप संकलन समय पर नहीं जानते हैं।यह एक चर होना चाहिए जिसका स्थिर प्रकार object या कुछ अन्य संदर्भ प्रकार है। हाउवर, क्योंकि Nullable<T> बॉक्स बॉक्स T मान पर मान बॉक्स, कोई बॉक्सिंग Nullable<T> जैसी कोई चीज़ नहीं है। वह उदाहरण जिसका प्रकार आपकी जांच केवल T होगी।

यही कारण है कि आप is int और is Nullable<int> के लिए एक ही परिणाम प्राप्त करते हैं। बॉक्स किए गए int और बॉक्स किए गए int? के बीच अंतर करने का कोई तरीका नहीं है, क्योंकि int? कोई बॉक्स नहीं है।

विवरण के लिए Nulls not missing anymore देखें।

0

जैसा कि पहले ही यह इंगित किया गया है कि null में कोई प्रकार नहीं है। यह पता लगाने के लिए कि int? बनाम long? है, तो आपको टाइप करने वाले किसी चीज़ के बारे में जानकारी प्राप्त करने के लिए प्रतिबिंब का उपयोग करने की आवश्यकता है। यहाँ कुछ कोड है कि आप प्रेरणा के रूप में उपयोग करने के लिए सक्षम हो सकता है (वास्तव में जानते हुए भी कि तुम क्या कोड प्राप्त करने के लिए कोशिश नहीं थोड़ा अजीब है):

class Pair<T> where T : struct { 

    public Pair(T? a, T? b) { 
    A = a; 
    B = b; 
    } 

    public T? A { get; private set; } 

    public T? B { get; private set; } 

} 

void DoSomething<T>(Pair<T> pair) where T : struct { 
    DoMore(pair); 
} 

void DoMore(params object[] args) { 
    Console.WriteLine("Do more"); 
    var nullableIntPairs = args.Where(IsNullableIntPair); 
    foreach (Pair<int> pair in nullableIntPairs) { 
    Console.WriteLine(pair.A); 
    Console.WriteLine(pair.B); 
    } 
} 

bool IsNullableIntPair(object arg) { 
    var type = arg.GetType(); 
    return type.IsGenericType 
    && type.GetGenericTypeDefinition() == typeof(Pair<>) 
    && type.GetGenericArguments()[0] == typeof(int); 
} 

आप निम्नलिखित कोड

DoSomething(new Pair<int>(5, new int?())); 
DoSomething(new Pair<long>(new long?(), 6L)); 

पर अमल करते हैं

 
Do more 
5 
null 
Do more 
0

आप उपयोग कर सकते हैं typeof:

a == typeof(Nullable<int>) //true 
a == typeof(int) //false 
आप निम्नलिखित आउटपुट प्राप्त
संबंधित मुद्दे