ऑब्जेक्ट रेफरेंस ऑब्जेक्ट के इंस्टेंस पर सेट नहीं है। वह .NET क्यों नहीं दिखाता है कि कौन सा ऑब्जेक्ट `null` है?


103

इस .NET के संबंध में अपवादित संदेश:

वस्तु का संदर्भ वस्तु की आवृत्ति अनुसार सेट नहीं। है।

.NET क्यों नहीं दिखाता है कि कौन सी वस्तु है null?

मुझे पता है कि मैं nullत्रुटि की जांच कर सकता हूं और हल कर सकता हूं । हालाँकि, .NET क्यों यह इंगित करने में मदद नहीं करता है कि किस ऑब्जेक्ट का अशक्त-संदर्भ है और किस अभिव्यक्ति ने ट्रिगर किया है NullReferenceException?

c#  .net 

2
जब ऐसा होता है, तो उस पंक्ति को फिर से लिखें, ताकि यह पहले अशक्त के लिए प्रत्येक संभावित परिणाम की जांच करे - फिर आपको पता चल जाएगा कि यह वास्तव में क्या था। या तो, या विजुअल स्टूडियो का अद्भुत डिबगर जुड़ा हुआ है, जो तुरंत एक अपवाद को तोड़ता है और आपको यह देखने देता है कि क्या अशक्त है :)
Patashu

5
वास्तव में नहीं, वह बस पूछता है कि .NET फ्रेमवर्क प्रोग्रामर को यह दिखाने में मदद नहीं करता है कि कौन सी वस्तु अशक्त है। मुझे लगता है कि यह प्रदर्शन जुर्माना है (आपको प्रतिबिंब की आवश्यकता होगी)। लेकिन मुझे यकीन नहीं है।
बस

1
@bas: जबकि यह सच है, सवाल थोड़ा भ्रामक है कि इसमें "अभिव्यक्ति का एक हिस्सा" के बारे में पूछा जाना चाहिए, न कि एक "वस्तु"। यह भी बताता है कि केवल प्रतिबिंब क्यों मदद नहीं करेगा, लेकिन कुछ व्यापक डिबग जानकारी की आवश्यकता होगी।
या मैपर

4
फिर भी मैं उत्तर के लिए उत्सुक हूं। यह एक .net अपवाद के समान है जो यह इंगित करने में मदद नहीं करता है कि किस शब्दकोष में कुंजी मौजूद नहीं है। इसके अलावा, मुझे इस सवाल पर भक्तों की समझ नहीं है।
बेस

12
शब्दावली कृपया: एक वस्तु कभी शून्य नहीं होती है। एक वस्तु संदर्भ हालांकि हो सकता है। लेकिन एक ऑब्जेक्ट संदर्भ स्मृति में सिर्फ एक स्थान है - यह आपकी मदद कैसे करेगा, जब तक कि आपके पास वैसे भी डिबगर संलग्न न हो?
Oskar Berggren

जवाबों:


169

(विजुअल स्टूडियो 2017 में नए अपवाद सहायक के बारे में जानकारी के लिए इस उत्तर का अंत देखें)


इस कोड पर विचार करें:

String s = null;
Console.WriteLine(s.Length);

यह NullReferenceExceptionदूसरी पंक्ति में फेंक देगा और आप जानना चाहते हैं कि .NET आपको यह क्यों नहीं बताता है कि sअपवाद के फेंकने पर यह अशक्त था।

यह समझने के लिए कि आपको जानकारी का वह टुकड़ा क्यों नहीं मिला, जिसे आपको याद रखना चाहिए कि यह C # स्रोत नहीं है जो निष्पादित करता है, बल्कि IL:

IL_0001: ldnull      
IL_0002: stloc.0 // s
IL_0003: ldloc.0 // s
IL_0004: callvirt System.String.get_Length
IL_0009: Call System.Console.WriteLine

यह callvirtओपकोड है जो फेंकता है NullReferenceExceptionऔर यह करता है कि जब मूल्यांकन स्टैक पर पहला तर्क एक अशक्त संदर्भ है (जो कि उपयोग करके लोड किया गया था ldloc.0)।

अगर .NET को यह बताने में सक्षम होना चाहिए कि यह sएक अशक्त संदर्भ था, तो इसे किसी तरह से ट्रैक करना चाहिए कि मूल्यांकन स्टैक मूल रूप पर पहला तर्क s। इस मामले में हमारे लिए यह देखना आसान है कि यह हैs अशक्त था लेकिन क्या होगा यदि मूल्य किसी अन्य फ़ंक्शन कॉल से वापसी मान था और किसी भी चर में संग्रहीत नहीं किया गया था? वैसे भी, इस तरह की जानकारी वह नहीं है जो आप वर्चुअल मशीन जैसे .NET वर्चुअल मशीन में ट्रैक करना चाहते हैं।


इस समस्या से बचने के लिए मेरा सुझाव है कि आप सभी सार्वजनिक पद्धति कॉल में तर्क-वितर्क की जाँच करें (जब तक कि आप अशक्त संदर्भ की अनुमति न दें):

public void Foo(String s) {
  if (s == null)
    throw new ArgumentNullException("s");
  Console.WriteLine(s.Length);
}

यदि नल को विधि से पास किया जाता है तो आपको एक अपवाद मिलता है जो ठीक बताता है कि समस्या क्या है ( sयह शून्य है)।


चार साल बाद विजुअल स्टूडियो 2017 में अब एक नया अपवाद सहायक है जो यह बताने की कोशिश करेगा कि एक NullReferenceExceptionफेंक दिए जाने पर क्या अशक्त है। यह आपको आवश्यक जानकारी देने में सक्षम है जब यह एक विधि का वापसी मूल्य है जो शून्य है:

दृश्य स्टूडियो 2017 अपवाद सहायक

ध्यान दें कि यह केवल एक DEBUG बिल्ड में काम करता है।


5
पंक्ति संख्याएँ और स्रोत फ़ाइल नाम IL कोड में ही संग्रहीत नहीं हैं, या तो हैं या वे हैं? फिर भी, उन्हें डिबगिंग के लिए उपलब्ध कराया जा सकता है।
या मैपर

4
@MartinLiversage: बिल्कुल सही। तो यह सवाल उबलता है: प्रतीक फ़ाइलों में संग्रहीत पर्याप्त जानकारी क्यों नहीं है जो यह भी बताती है कि कोड में किस अभिव्यक्ति का मूल्यांकन किया गया था null
या मैपर

2
@MartinLiversage: प्रतीक फाइलें एक तरह से सुलभ हैं ताकि अपवाद संदेश के साथ, डिबगर के आउटपुट में स्रोत फ़ाइल और लाइन नंबर प्रदर्शित किया जा सके। तो, सवाल यह है कि क्या वास्तव में लौटे पर कुछ और जानकारी शामिल करने का कारण नहीं है null- ध्यान दें कि ओपी यह दावा नहीं करता है कि वह जानना चाहता है कि रिलीज के लिए, साथ ही, डिबग बिल्ड पर्याप्त हो सकते हैं।
या मैपर

3
हम्म, और हमें यह नहीं भूलना चाहिए कि यह आईएल भी नहीं है जो वास्तव में निष्पादित करता है, बल्कि रनटाइम पर इसे बनाया गया देशी कोड।
Oskar Berggren

2
@MartinLiversage: इस प्रश्न का कोई भी दावा नहीं करता कि हम चाहते हैं कि यह रिलीज़ बिल्ड के लिए पूरी तरह से समर्थित हो। वैसे भी, मैं उस ऑब्जेक्ट संदर्भ का उपयोग करने nullवाले स्रोत फ़ाइल लाइन और स्तंभ के साथ ऑब्जेक्ट संदर्भ का उपयोग करने वाले IL opcode को सम्‍मिलित करने में समस्‍या नहीं देखता (जो हो सकता है )।
या मैपर

9

आप निम्नलिखित मामले में त्रुटि संदेश कैसे चाहते हैं?

AnyObject.GetANullObject().ToString();

private object GetANullObject()
{
  return null;
}

कोई चर नाम यहाँ रिपोर्ट करने के लिए!


2
मुझे संदेह है कि ओपी स्रोत कोड में अभिव्यक्ति की तलाश में है जो अशक्त देता है, न कि वस्तु। मैंने प्रश्न से संबंधित टिप्पणी जोड़ दी है और आशा है कि वह चीजों को स्पष्ट करेगा। यदि मेरा संदेह सही है, तो ओपी Object reference obtained from AnyObject.GetANullObject() not set to an instance of an object.त्रुटि संदेश की तरह कुछ उम्मीद करेगा ।
या मैपर

1
@ सहकर्मी मैं सहमत हूं। मैं ओपी के लिए एक टिप्पणी में सिर्फ अपना "जवाब" डाल सकता था, अगर मेरे पास टिप्पणी जोड़ने के लिए पर्याप्त प्रतिष्ठा अंक थे!
रोमर

1
"क्लास एक्सवाईजेड की टोस्ट्रिंग () पद्धति को कॉल करने का प्रयास किया गया एक अशक्त संदर्भ" जो अब हमें मिलता है उससे अधिक सहायक होगा।
माइकल लेवी

सबसे उपयोगी बात यह होगी कि प्रत्येक कॉल स्तर पर, एक स्टैक ट्रेस दिखा रहा है, बिल्कुल किस लाइन में, किस फाइल में त्रुटि हुई। ओह, रुको ... अब यह क्या करता है!
जिम बाल्टर

1

ठीक है, यह जवाब देने के लिए माइक्रोसॉफ्ट के इंजीनियरों तक है। लेकिन आप स्पष्ट रूप से डिबगर का उपयोग कर सकते हैं और यह पता लगाने के लिए घड़ी जोड़ सकते हैं कि उनमें से कौन सी समस्या है।

हालाँकि, अपवाद NullReferenceExceptionजिसका अर्थ है कि संदर्भ मौजूद नहीं है । आपको वह वस्तु नहीं मिल सकती है जो बिल्कुल नहीं बनाई गई है।

but why .NET don't tell us which object is null? क्योंकि यह नहीं जानता कि कौन सी वस्तु अशक्त है। वस्तु बस मौजूद नहीं है!

जब मैं कहता हूं तब भी यही स्थिति होती है। C # को .NET IL कोड में संकलित किया जाता है। .NET IL कोड नाम या भाव नहीं जानता है। यह केवल संदर्भों और उनके स्थान को जानता है। यहां भी, आपको वह नहीं मिल सकता है जो मौजूद नहीं है। अभिव्यक्ति या चर नाम मौजूद नहीं है।

दार्शनिक: यदि आपके पास पहली जगह में अंडा नहीं है, तो आप एक चूक नहीं कर सकते।


3
कि एक जवाब नहीं है या तो :)
बस

यदि यह मौजूद नहीं है तो आपको संदर्भ कैसे मिलेगा? @ बास
अनिकेत इंग

4
"ठीक है, यह जवाब देने के लिए माइक्रोसॉफ्ट के इंजीनियरों तक है।" तो उन्हें इस पर एक प्रकाश डाला बजाय बताते हुए स्पष्ट की जाने
बस

@बस हम तय कर सकते हैं कि बहुत कम से कम तार्किक क्या है। तार्किक रूप से वस्तु मौजूद नहीं है। आप इसे अपवाद के साथ कैसे पकड़ेंगे और फिर ऑब्जेक्ट का नाम प्रिंट करेंगे? यह सिर्फ मौजूद नहीं है। स्टैक पर भी नहीं ..
अनिकेत इंग

तो इसका उत्तर यह है कि वास्तव में यह बताना असंभव है कि किस वस्तु में अशक्तता है? वह भी एक उत्तर है। मैं यह नहीं कह रहा हूं कि मुझे पता है, मुझे सिर्फ सवाल पसंद है :)। +1 सभी प्रयासों के लिए: पी
बेस

1

निश्चित नहीं है, लेकिन ऐसा हो सकता है क्योंकि .Net नहीं जानता कि यह पूर्वनिर्धारित वर्ग है या उपयोगकर्ता द्वारा परिभाषित है। यदि इसे पूर्वनिर्धारित किया जाता है तो यह अशक्त हो सकता है (जैसे स्ट्रिंग जो 2 बाइट्स पर कब्जा कर लेती है) लेकिन अगर यह उपयोगकर्ता द्वारा परिभाषित किया गया है तो हमें इसका एक उदाहरण बनाना होगा ताकि यह पता चले कि यह ऑब्जेक्ट इस बहुत अधिक मेमोरी पर कब्जा कर लेगा। इसलिए, यह रन-टाइम पर त्रुटि फेंकता है।


-2

अच्छा प्रश्न। मैसेज बॉक्स बेकार है। यहां तक ​​कि अगर यह संदर्भ परिभाषा से एक मील की गहराई तक दफन है, तो कुछ वर्ग या असेंबली या फ़ाइल या अन्य जानकारी वर्तमान में जो वे प्रदान करते हैं उससे बेहतर होगा (पढ़ें: कुछ भी नहीं से बेहतर)।

आपका सबसे अच्छा विकल्प डिबगिंग जानकारी के साथ डीबगर में इसे चलाना है, और आपका आईडीई आक्रामक रेखा पर टूट जाएगा (बल्कि स्पष्ट रूप से प्रदर्शित करना कि उपयोगी जानकारी वास्तव में उपलब्ध है)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.