सवाल NullReferenceException क्या है, और मैं इसे कैसे ठीक करूं?


मेरे पास कुछ कोड है और जब यह निष्पादित होता है, तो यह फेंकता है NullReferenceException, कह रही है:

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

इसका क्या अर्थ है, और मैं इस त्रुटि को ठीक करने के लिए क्या कर सकता हूं?


1878


मूल


वीएस 2017 में अपवाद सहायक इस अपवाद के कारण का निदान करने में अधिक सहायक होगा - blogs.msdn.microsoft.com/visualstudio/2016/11/28/... के अंतर्गत नई अपवाद सहायक। - Zev Spitz
क्या हम बस कहते हैं "ऑब्जेक्ट शुरू नहीं किया गया है"? तो यदि आपके पास एक परिवर्तनीय घोषणा है: SomeClass myVariable; यह SomeClass के संदर्भ में myVariable बना देगा, लेकिन यह प्रारंभ नहीं किया गया है और शून्य के बराबर होगा। आपको SomeClass myVariable = new SomeClass () करके क्लास प्रारंभिकरण का आह्वान करना होगा; या, यदि आप किसी अन्य चर के संदर्भ को वापस कर रहे हैं: SomeClass myVariable = anotherVariableDeclared (); - Arvin Amir
@ आर्विन 'एमएफ क्लास के बारे में क्या - John Saunders
प्रिय भविष्य के आगंतुक, इस प्रश्न का उत्तर समान रूप से लागू होता है ArgumentNullException। यदि आपका प्रश्न इस के डुप्लिकेट के रूप में बंद कर दिया गया है, और आप एएनई का अनुभव कर रहे हैं, तो कृपया डीबग करने और अपनी समस्या को ठीक करने के उत्तरों में दिशानिर्देशों का पालन करें। - Will
@ एएनई केवल तभी होना चाहिए जब एक नल पैरामीटर के रूप में पारित हो। क्या आप एक उदाहरण दे सकते हैं यदि कोई एएनई प्रश्न इस के डुप्लिकेट के रूप में बंद हो जाता है? - John Saunders


जवाब:


कारण क्या है?

जमीनी स्तर

आप कुछ ऐसा करने की कोशिश कर रहे हैं null (या Nothing वीबीएनईटी में)। इसका मतलब है कि आप या तो इसे सेट करें null, या आप इसे किसी भी चीज़ पर कभी भी सेट नहीं करते हैं।

किसी और चीज की तरह, null चारों ओर पारित हो जाता है। अगर यह होता है null  में विधि "ए", यह विधि "बी" पारित हो सकती है null  सेवा मेरे विधि "ए"।

null अलग-अलग अर्थ हो सकते हैं:

  1. ऑब्जेक्ट वेरिएबल्स जो हैं अप्रारंभीकृत और इसलिए कुछ भी इंगित करें। इस मामले में, यदि आप ऐसी वस्तुओं के गुण या विधियों तक पहुंचते हैं, तो यह एक कारण बनता है NullReferenceException
  2. डेवलपर है का उपयोग करते हुए null जानबूझकर यह इंगित करने के लिए कोई सार्थक मूल्य उपलब्ध नहीं है। ध्यान दें कि सी # में चर के लिए निरर्थक डेटाटाइप की अवधारणा है (जैसे डेटाबेस टेबल में शून्य फ़ील्ड हो सकते हैं) - आप असाइन कर सकते हैं null उनके लिए यह इंगित करने के लिए कि इसमें कोई मूल्य संग्रहित नहीं है, उदाहरण के लिए int? a = null; जहां प्रश्न चिह्न इंगित करता है कि इसे परिवर्तनीय में शून्य स्टोर करने की अनुमति है a। आप इसे या तो देख सकते हैं if (a.HasValue) {...} या के साथ if (a==null) {...}। नामुमकिन चर, जैसे a यह उदाहरण, के माध्यम से मूल्य तक पहुंचने की अनुमति देता है a.Value स्पष्ट रूप से, या बस के रूप में सामान्य के रूप में a
    ध्यान दें जो इसे एक्सेस कर रहा है a.Value फेंकता है InvalidOperationException के बजाय एक NullReferenceException अगर a है null - आपको पहले से चेक करना चाहिए, यानी यदि आपके पास एक और ऑन-न्यूबल परिवर्तनीय है int b; तो आपको असाइनमेंट करना चाहिए if (a.HasValue) { b = a.Value; } या छोटा if (a != null) { b = a; }

इस लेख का बाकी विवरण अधिक विस्तार से चला जाता है और गलतियों को दिखाता है कि कई प्रोग्रामर अक्सर ऐसा करते हैं जो एक को जन्म दे सकता है NullReferenceException

अधिक विशेष रूप से

रनटाइम फेंकना NullReferenceException  हमेशा मतलब एक ही बात है: आप एक संदर्भ का उपयोग करने की कोशिश कर रहे हैं, और संदर्भ प्रारंभ नहीं किया गया है (या यह था एक बार शुरू किया, लेकिन है अब और नहीं प्रारंभ)।

इसका मतलब है संदर्भ है null, और आप सदस्यों के माध्यम से सदस्यों (जैसे विधियों) तक नहीं पहुंच सकते हैं null संदर्भ। सबसे आसान मामला:

string foo = null;
foo.ToUpper();

यह एक फेंक देगा NullReferenceException दूसरी पंक्ति पर क्योंकि आप आवृत्ति विधि को कॉल नहीं कर सकते हैं ToUpper() पर string संदर्भ इंगित करता है null

डिबगिंग

आपको ए के स्रोत कैसे मिलते हैं NullReferenceException? अपवाद को देखने के अलावा, जो उस स्थान पर बिल्कुल फेंक दिया जाएगा जहां दृश्य होता है, विजुअल स्टूडियो में डिबगिंग के सामान्य नियम लागू होते हैं: रणनीतिक ब्रेकपॉइंट्स रखें और अपने चर का निरीक्षण करें, या तो अपने नामों पर माउस को घुमाने, एक (त्वरित) घड़ी विंडो खोलने या स्थानीय और ऑटोस जैसे विभिन्न डीबगिंग पैनलों का उपयोग करके।

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

प्रोग्राम प्रवाह का पालन करके इस तरह से, आप उस स्थान को पा सकते हैं जहां इंस्टेंस शून्य नहीं होना चाहिए, और यह ठीक से सेट क्यों नहीं है।

उदाहरण

कुछ सामान्य परिदृश्य जहां अपवाद फेंक दिया जा सकता है:

सामान्य

ref1.ref2.ref3.member

यदि ref1 या ref2 या ref3 शून्य है, तो आपको एक मिल जाएगा NullReferenceException। यदि आप समस्या को हल करना चाहते हैं, तो यह पता लगाएं कि अभिव्यक्ति को इसके सरल समकक्ष में फिर से लिखकर कौन सा शून्य है:

var r1 = ref1;
var r2 = r1.ref2;
var r3 = r2.ref3;
r3.member

विशेष रूप से, में HttpContext.Current.User.Identity.Name, द HttpContext.Current शून्य हो सकता है, या User संपत्ति शून्य हो सकती है, या Identity संपत्ति शून्य हो सकती है।

अप्रत्यक्ष

public class Person {
    public int Age { get; set; }
}
public class Book {
    public Person Author { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; // You never initialized the Author property.
                                       // there is no Person to get an Age from.
    }
}

यदि आप बच्चे (व्यक्ति) शून्य संदर्भ से बचना चाहते हैं, तो आप इसे मूल (पुस्तक) ऑब्जेक्ट के कन्स्ट्रक्टर में प्रारंभ कर सकते हैं।

नेस्टेड ऑब्जेक्ट प्रारंभकर्ता

यह नेस्टेड ऑब्जेक्ट प्रारंभकर्ताओं पर भी लागू होता है:

Book b1 = new Book { Author = { Age = 45 } };

यह अनुवाद करता है

Book b1 = new Book();
b1.Author.Age = 45;

जबकि new कीवर्ड का उपयोग किया जाता है, यह केवल एक नया उदाहरण बनाता है Book, लेकिन एक नया उदाहरण नहीं है Person, ऐसा Author संपत्ति अभी भी है null

नेस्टेड संग्रह प्रारंभकर्ता

public class Person {
    public ICollection<Book> Books { get; set; }
}
public class Book {
    public string Title { get; set; }
}

नेस्टेड संग्रह प्रारंभकर्ता एक ही व्यवहार करते हैं:

Person p1 = new Person {
    Books = {
        new Book { Title = "Title1" },
        new Book { Title = "Title2" },
    }
};

यह अनुवाद करता है

Person p1 = new Person();
p1.Books.Add(new Book { Title = "Title1" });
p1.Books.Add(new Book { Title = "Title2" });

new Person केवल एक उदाहरण बनाता है Person, लेकिन वो Books संग्रह अभी भी है null। संग्रह प्रारंभकर्ता वाक्यविन्यास संग्रह नहीं बनाता है के लिये p1.Books, यह केवल अनुवाद करता है p1.Books.Add(...) बयान।

सरणी

int[] numbers = null;
int n = numbers[0]; // numbers is null. There is no array to index.

ऐरे तत्व

Person[] people = new Person[5];
people[0].Age = 20 // people[0] is null. The array was allocated but not
                   // initialized. There is no Person to set the Age for.

जालीदार Arrays

long[][] array = new long[1][];
array[0][0] = 3; // is null because only the first dimension is yet initialized.
                 // Use array[0] = new long[2]; first.

संग्रह / सूची / शब्दकोश

Dictionary<string, int> agesForNames = null;
int age = agesForNames["Bob"]; // agesForNames is null.
                               // There is no Dictionary to perform the lookup.

रेंज वेरिएबल (अप्रत्यक्ष / स्थगित)

public class Person {
    public string Name { get; set; }
}
var people = new List<Person>();
people.Add(null);
var names = from p in people select p.Name;
string firstName = names.First(); // Exception is thrown here, but actually occurs
                                  // on the line above.  "p" is null because the
                                  // first element we added to the list is null.

आयोजन

public class Demo
{
    public event EventHandler StateChanged;

    protected virtual void OnStateChanged(EventArgs e)
    {        
        StateChanged(this, e); // Exception is thrown here 
                               // if no event handlers have been attached
                               // to StateChanged event
    }
}

खराब नामकरण सम्मेलन:

यदि आपने स्थानीय लोगों से अलग-अलग फ़ील्ड नाम दिए हैं, तो हो सकता है कि आपने महसूस किया हो कि आपने कभी भी फ़ील्ड शुरू नहीं की है।

public class Form1 {
    private Customer customer;

    private void Form1_Load(object sender, EventArgs e) {
        Customer customer = new Customer();
        customer.Name = "John";
    }

    private void Button_Click(object sender, EventArgs e) {
        MessageBox.Show(customer.Name);
    }
}

अंडरस्कोर वाले फ़ील्ड उपसर्ग के लिए सम्मेलन का पालन करके इसे हल किया जा सकता है:

private Customer _customer;

एएसपी.नेट पृष्ठ जीवन चक्र:

public partial class Issues_Edit : System.Web.UI.Page
{
    protected TestIssue myIssue;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // Only called on first load, not when button clicked
            myIssue = new TestIssue(); 
        }
    }

    protected void SaveButton_Click(object sender, EventArgs e)
    {
        myIssue.Entry = "NullReferenceException here!";
    }
}

एएसपी.NET सत्र मूल्य

// if the "FirstName" session value has not yet been set,
// then this line will throw a NullReferenceException
string firstName = Session["FirstName"].ToString();

एएसपी.नेट एमवीसी खाली दृश्य मॉडल

यदि किसी संपत्ति का संदर्भ देते समय अपवाद होता है @Model एक एएसपी.नेट एमवीसी दृश्य में, आपको यह समझने की जरूरत है कि Model जब आप अपनी क्रिया विधि में सेट हो जाता है return एक दृश्य। जब आप अपने नियंत्रक से एक खाली मॉडल (या मॉडल प्रॉपर्टी) वापस करते हैं, तो अपवाद तब होता है जब विचार इसे एक्सेस करते हैं:

// Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
         return View();  // Forgot the provide a Model here.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Throws.
{
}

<p>@Model.somePropertyName</p> <!-- Also throws -->

डब्ल्यूपीएफ नियंत्रण निर्माण आदेश और घटनाक्रम

कॉल के दौरान WPF नियंत्रण बनाए जाते हैं InitializeComponent क्रम में वे दृश्य पेड़ में दिखाई देते हैं। ए NullReferenceException इवेंट हैंडलर इत्यादि के साथ शुरुआती बनाए गए नियंत्रणों के मामले में उठाया जाएगा, जो कि आग लगती है InitializeComponent जो देर से बनाए गए नियंत्रणों का संदर्भ देता है।

उदाहरण के लिए :

<Grid>
    <!-- Combobox declared first -->
    <ComboBox Name="comboBox1" 
              Margin="10"
              SelectedIndex="0" 
              SelectionChanged="comboBox1_SelectionChanged">
        <ComboBoxItem Content="Item 1" />
        <ComboBoxItem Content="Item 2" />
        <ComboBoxItem Content="Item 3" />
    </ComboBox>

    <!-- Label declared later -->
    <Label Name="label1" 
           Content="Label"
           Margin="10" />
</Grid>

यहाँ comboBox1 पहले बनाया गया है label1। अगर comboBox1_SelectionChanged `लेबल 1 को संदर्भित करने का प्रयास, यह अभी तक नहीं बनाया जाएगा।

private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    label1.Content = comboBox1.SelectedIndex.ToString(); // NullReference here!!
}

XAML में घोषणाओं के क्रम को बदलना (यानी, लिस्टिंग label1 से पहले comboBox1, डिजाइन दर्शन के मुद्दों को अनदेखा करते हुए, कम से कम हल करेंगे NullReferenceException यहाँ।

के साथ कास्ट करें as

var myThing = someObject as Thing;

यह एक अवैधCastException फेंक नहीं है लेकिन एक देता है null जब कास्ट विफल रहता है (और जब कुछ ऑब्जेक्ट स्वयं शून्य होता है)। तो इसके बारे में जागरूक रहें।

LINQ FirstOrDefault () और SingleOrDefault ()

सादे संस्करण First() तथा Single() कुछ भी नहीं होने पर अपवाद फेंक दें। "OrDefault" संस्करण उस मामले में शून्य वापस आते हैं। तो इसके बारे में जागरूक रहें।

प्रत्येक के लिए

foreach जब आप शून्य संग्रह को पुन: प्रयास करने का प्रयास करते हैं तो फेंकता है। आमतौर पर अप्रत्याशित के कारण होता है null संग्रहों को वापस करने वाले तरीकों से परिणाम।

 List<int> list = null;    
 foreach(var v in list) { } // exception

अधिक यथार्थवादी उदाहरण - एक्सएमएल दस्तावेज़ से नोड्स का चयन करें। यदि नोड्स नहीं मिलते हैं तो फेंक देंगे लेकिन प्रारंभिक डीबगिंग से पता चलता है कि सभी गुण मान्य हैं:

 foreach (var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))

से बचने के तरीके

स्पष्ट रूप से जांचें null और शून्य मूल्यों को अनदेखा करें।

यदि आप संदर्भ को कभी-कभी शून्य होने की अपेक्षा करते हैं, तो आप इसकी जांच कर सकते हैं null उदाहरण सदस्यों तक पहुंचने से पहले:

void PrintName(Person p) {
    if (p != null) {
        Console.WriteLine(p.Name);
    }
}

स्पष्ट रूप से जांचें null और एक डिफ़ॉल्ट मान प्रदान करते हैं।

जिस तरीके से आप एक उदाहरण वापस करने की उम्मीद करते हैं उसे वापस कर सकते हैं null, उदाहरण के लिए जब वस्तु की मांग की जा सकती है। जब यह मामला है तो आप डिफ़ॉल्ट मान वापस करना चुन सकते हैं:

string GetCategory(Book b) {
    if (b == null)
        return "Unknown";
    return b.Category;
}

स्पष्ट रूप से जांचें null विधि कॉल से और एक कस्टम अपवाद फेंक दें।

आप एक कस्टम अपवाद भी फेंक सकते हैं, केवल कॉलिंग कोड में इसे पकड़ने के लिए:

string GetCategory(string bookTitle) {
    var book = library.FindBook(bookTitle);  // This may return null
    if (book == null)
        throw new BookNotFoundException(bookTitle);  // Your custom exception
    return book.Category;
}

उपयोग Debug.Assert यदि कोई मूल्य कभी नहीं होना चाहिए nullअपवाद की तुलना में पहले समस्या को पकड़ने के लिए।

जब आप विकास के दौरान जानते हैं कि एक विधि शायद हो सकती है, लेकिन कभी वापस नहीं आना चाहिए null, आप उपयोग कर सकते हैं Debug.Assert() जितनी जल्दी हो सके तो इसे तोड़ने के लिए:

string GetTitle(int knownBookID) {
    // You know this should never return null.
    var book = library.GetBook(knownBookID);  

    // Exception will occur on the next line instead of at the end of this method.
    Debug.Assert(book != null, "Library didn't return a book for known book ID.");

    // Some other code

    return book.Title; // Will never throw NullReferenceException in Debug mode.
}

हालांकि यह जांच आपके रिलीज बिल्ड में खत्म नहीं होगा, इसे फेंकने के कारण NullReferenceException फिर कब book == null रिलीज मोड में रनटाइम पर।

उपयोग GetValueOrDefault() जब वे हैं तो एक डिफ़ॉल्ट मान प्रदान करने के लिए शून्य मूल्य प्रकार के लिए null

DateTime? appointment = null;
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Will display the default value provided (DateTime.Now), because appointment is null.

appointment = new DateTime(2022, 10, 20);
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Will display the appointment date, not the default

नल कोलेसिंग ऑपरेटर का प्रयोग करें: ?? [सी #] या If() [वीबी]।

एक डिफ़ॉल्ट मूल्य प्रदान करने के लिए shorthand जब एक null सामना किया गया है:

IService CreateService(ILogger log, Int32? frobPowerLevel)
{
    var serviceImpl = new MyService(log ?? NullLog.Instance);

    // Note that the above "GetValueOrDefault()" can also be rewritten to use
    // the coalesce operator:
    serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5;
}

शून्य स्थिति ऑपरेटर का प्रयोग करें: ?. या ?[x] सरणी के लिए (सी # 6 और वीबी.नेट 14 में उपलब्ध):

इसे कभी-कभी सुरक्षित नेविगेशन या एल्विस (इसके आकार के बाद) ऑपरेटर भी कहा जाता है। यदि ऑपरेटर के बाईं तरफ की अभिव्यक्ति शून्य है, तो दाएं तरफ का मूल्यांकन नहीं किया जाएगा, और इसके बजाय शून्य वापस कर दिया जाएगा। इसका मतलब है कि इस तरह के मामलों:

var title = person.Title.ToUpper();

अगर व्यक्ति के पास शीर्षक नहीं है, तो यह एक अपवाद फेंक देगा क्योंकि यह कॉल करने का प्रयास कर रहा है ToUpper एक शून्य मूल्य के साथ एक संपत्ति पर।

सी # 5 और नीचे में, इसकी सुरक्षा की जा सकती है:

var title = person.Title == null ? null : person.Title.ToUpper();

अब शीर्षक चर अपवाद फेंकने के बजाय शून्य होगा। सी # 6 इसके लिए एक छोटा वाक्यविन्यास प्रस्तुत करता है:

var title = person.Title?.ToUpper();

इसके परिणामस्वरूप शीर्षक परिवर्तनीय होगा null, और कॉल करने के लिए ToUpper अगर नहीं बनाया जाता है person.Title है null

बेशक तुम फिर भी जांचना है title शून्य के लिए या नल कंडीशनिंग ऑपरेटर के साथ शून्य स्थिति ऑपरेटर का उपयोग करें (??) एक डिफ़ॉल्ट मूल्य की आपूर्ति करने के लिए:

// regular null check
int titleLength = 0;
if (title != null)
    titleLength = title.Length; // If title is null, this would throw NullReferenceException

// combining the `?` and the `??` operator
int titleLength = title?.Length ?? 0;

इसी तरह, सरणी के लिए आप उपयोग कर सकते हैं ?[i] निम्नलिखित नुसार:

int[] myIntArray=null;
var i=5;
int? elem = myIntArray?[i];
if (!elem.HasValue) Console.WriteLine("No value");

यह निम्न कार्य करेगा: यदि myIntArray शून्य है, तो अभिव्यक्ति शून्य हो जाती है और आप इसे सुरक्षित रूप से देख सकते हैं। यदि इसमें एक सरणी है, तो यह वही होगा: elem = myIntArray[i]; और मैं लौटाता हूंवें तत्व।

Iterators में null derefs डीबगिंग और फिक्सिंग के लिए विशेष तकनीकें

सी # "इटरेटर ब्लॉक" का समर्थन करता है (जिसे कुछ अन्य लोकप्रिय भाषाओं में "जेनरेटर" कहा जाता है)। स्थगित निष्पादन की वजह से निरंतर अपवादों को अपरेटर ब्लॉक में डीबग करना विशेष रूप से मुश्किल हो सकता है:

public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}
...
FrobFactory factory = whatever;
IEnumerable<Frobs> frobs = GetFrobs();
...
foreach(Frob frob in frobs) { ... }

अगर whatever का परिणाम null फिर MakeFrob फेंक देगा अब, आप सोच सकते हैं कि सही काम यह है:

// DON'T DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    if (f == null) 
      throw new ArgumentNullException("f", "factory must not be null");
    for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}

यह गलत क्यों है? क्योंकि इटरेटर ब्लॉक वास्तव में नहीं है रन जब तक foreach! कॉल करने के लिए GetFrobs बस एक वस्तु देता है जो जब पुनरावृत्त इटरेटर ब्लॉक चलाएगा।

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

सही फिक्स है:

// DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    // No yields in a public method that throws!
    if (f == null) 
      throw new ArgumentNullException("f", "factory must not be null");
    return GetFrobsForReal(f, count);
}
private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count)
{
    // Yields in a private method
    Debug.Assert(f != null);
    for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}

यही है, एक निजी सहायक विधि बनाएं जिसमें इटरेटर ब्लॉक तर्क है, और एक सार्वजनिक सतह विधि जो शून्य जांच करता है और इसे पुनरावर्तक देता है। अब जब GetFrobs कहा जाता है, शून्य जांच तत्काल होती है, और फिर GetFrobsForReal अनुक्रमित होने पर निष्पादित होता है।

यदि आप LINQ से ऑब्जेक्ट्स के संदर्भ स्रोत की जांच करते हैं तो आप देखेंगे कि इस तकनीक का उपयोग पूरे समय में किया जाता है। यह लिखने के लिए थोड़ा और अधिक कठोर है, लेकिन यह डिबगिंग नलिटी त्रुटियों को बहुत आसान बनाता है। कॉलर की सुविधा के लिए अपने कोड को अनुकूलित करें, लेखक की सुविधा नहीं

असुरक्षित कोड में शून्य dereferences पर एक नोट

सी # में एक "असुरक्षित" मोड है, जैसा कि नाम का तात्पर्य है, बेहद खतरनाक है क्योंकि सामान्य सुरक्षा तंत्र जो स्मृति सुरक्षा और प्रकार की सुरक्षा प्रदान करते हैं, लागू नहीं होते हैं। आपको असुरक्षित कोड नहीं लिखना चाहिए जब तक कि आपके पास मेमोरी कैसे काम करती है, इसकी पूरी और गहरी समझ हो

असुरक्षित मोड में, आपको दो महत्वपूर्ण तथ्यों से अवगत होना चाहिए:

  • एक निराशाजनक dereferencing सूचक एक निराशाजनक dereferencing के रूप में एक ही अपवाद पैदा करता है संदर्भ
  • एक अवैध गैर-शून्य सूचक को dereferencing कर सकते हैं उस अपवाद का उत्पादन करें कुछ परिस्थितियों में

यह समझने के लिए कि यह क्यों है, यह समझने में मदद करता है कि .NET पहली जगह में शून्य अपरिवर्तनीय अपवाद कैसे उत्पन्न करता है। (ये विवरण विंडोज़ पर चल रहे .NET पर लागू होते हैं; अन्य ऑपरेटिंग सिस्टम समान तंत्र का उपयोग करते हैं।)

विंडोज़ में मेमोरी वर्चुअलाइज्ड है; प्रत्येक प्रक्रिया को ऑपरेटिंग सिस्टम द्वारा ट्रैक किए गए स्मृति के कई "पृष्ठों" की वर्चुअल मेमोरी स्पेस मिलती है। स्मृति के प्रत्येक पृष्ठ पर झंडे सेट होते हैं जो निर्धारित करते हैं कि इसका उपयोग कैसे किया जा सकता है: से लिखा, लिखा, निष्पादित, और इसी तरह से। सबसे कम पृष्ठ को "किसी भी तरह से उपयोग किए जाने पर त्रुटि उत्पन्न करें" के रूप में चिह्नित किया गया है।

सी # में एक शून्य सूचक और शून्य संदर्भ दोनों आंतरिक रूप से संख्या शून्य के रूप में दर्शाए जाते हैं, और इसलिए इसे इसके संबंधित मेमोरी स्टोरेज में डिफरेंस करने का कोई भी प्रयास ऑपरेटिंग सिस्टम को त्रुटि उत्पन्न करने का कारण बनता है। .NET रनटाइम तब इस त्रुटि का पता लगाता है और इसे शून्य dereference अपवाद में बदल देता है।

यही कारण है कि एक शून्य सूचक और एक शून्य संदर्भ दोनों को संदर्भित करना एक ही अपवाद पैदा करता है।

दूसरे बिंदु के बारे में क्या? अपसंदर्भन कोई अमान्य सूचक जो वर्चुअल मेमोरी के निम्नतम पृष्ठ में आता है, उसी ऑपरेटिंग सिस्टम त्रुटि का कारण बनता है, और इसी तरह एक ही अपवाद होता है।

यह समझ में क्यों आता है? खैर, मान लीजिए कि हमारे पास दो चींटियां हैं, और एक अप्रबंधित पॉइंटर शून्य के बराबर है। यदि हम संरचना में दूसरी int को कम करने का प्रयास करते हैं, तो CLR स्थान शून्य पर संग्रहण तक पहुंचने का प्रयास नहीं करेगा; यह स्थान चार पर भंडारण का उपयोग करेगा। लेकिन तार्किक रूप से यह एक शून्य बेकार है क्योंकि हम उस पते पर जा रहे हैं के जरिए शून्य

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


2111



हो सकता है कि यह एक गूंगा टिप्पणी है लेकिन इस समस्या से बचने का पहला और सबसे अच्छा तरीका वस्तु को आरंभ करना है? मेरे लिए यदि यह त्रुटि होती है तो आमतौर पर ऐसा होता है क्योंकि मैं सरणी तत्व की तरह कुछ प्रारंभ करना भूल गया था। मुझे लगता है कि ऑब्जेक्ट को शून्य के रूप में परिभाषित करना बहुत कम आम है और फिर इसका संदर्भ लें। हो सकता है कि विवरण के समीप प्रत्येक समस्या को हल करने का तरीका दें। अभी भी एक अच्छी पोस्ट है। - JPK
क्या होगा यदि कोई वस्तु न हो, बल्कि किसी विधि या संपत्ति से वापसी मूल्य? - John Saunders
किताब / लेखक उदाहरण थोड़ा अजीब है .... यह कैसे संकलित करता है? इंटेलिजेंस कैसे काम करता है? यह क्या है मैं computar के साथ अच्छा नहीं हूँ ... - Will
@Will: क्या मेरा आखिरी संपादन मदद करता है? यदि नहीं, तो कृपया किसी समस्या के रूप में आप जो देखते हैं उसके बारे में अधिक स्पष्ट रहें। - John Saunders
@ जॉन सैंडर्स ओह, नहीं, क्षमा करें, मेरा मतलब ऑब्जेक्ट प्रारंभकर्ता संस्करण था। new Book { Author = { Age = 45 } }; आंतरिक प्रारंभिकता भी कैसे ... मैं ऐसी स्थिति के बारे में नहीं सोच सकता जहां आंतरिक init कभी काम करेगा, फिर भी यह संकलित और intellisense काम करता है ... structs के लिए जब तक? - Will


NullReference अपवाद - विजुअल बेसिक

NullReference Exception के लिये मूल दृश्य इनमें से कोई अलग नहीं है सी#। आखिरकार, वे दोनों .NET Framework में परिभाषित एक ही अपवाद की रिपोर्ट कर रहे हैं, जिसे वे दोनों उपयोग करते हैं। विजुअल बेसिक के लिए अद्वितीय कारण दुर्लभ हैं (शायद केवल एक)।

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

ध्यान दें:

  1. यह अवधारणा आधारित है: आपके प्रोजेक्ट में पेस्ट करने के लिए कोई कोड नहीं है। इसका उद्देश्य यह समझने में आपकी सहायता करना है कि क्या होता है NullReferenceException (एनआरई), इसे कैसे ढूंढें, इसे कैसे ठीक करें, और इससे कैसे बचें। एक एनआरई कई तरीकों से पैदा किया जा सकता है, इसलिए यह आपके एकमात्र मुठभेड़ होने की संभावना नहीं है।
  2. उदाहरण (स्टैक ओवरफ़्लो पोस्ट से) हमेशा पहले स्थान पर कुछ करने का सबसे अच्छा तरीका नहीं दिखाते हैं।
  3. आमतौर पर, सबसे सरल उपाय का उपयोग किया जाता है।

मूल अर्थ

संदेश "ऑब्जेक्ट ऑब्जेक्ट के उदाहरण पर सेट नहीं है" इसका मतलब है कि आप उस ऑब्जेक्ट का उपयोग करने की कोशिश कर रहे हैं जिसे प्रारंभ नहीं किया गया है। यह इनमें से एक को उबालता है:

  • तुम्हारा कोड घोषित एक ऑब्जेक्ट वैरिएबल, लेकिन ऐसा नहीं हुआ हस्ताक्षर करना यह (एक उदाहरण या 'इन्स्तांत करना'यह)
  • जो कुछ आपके कोड ने माना है वह किसी ऑब्जेक्ट को प्रारंभ करेगा, नहीं
  • संभवतः, अन्य कोड ने अभी भी उपयोग में एक ऑब्जेक्ट को अमान्य कर दिया है

कारण ढूँढना

चूंकि समस्या एक वस्तु संदर्भ है जो है Nothing, इसका जवाब यह जानने के लिए है कि कौन सा है। फिर निर्धारित करें कि इसे क्यों शुरू नहीं किया गया है। माउस को विभिन्न चरों पर रखें और विजुअल स्टूडियो (वीएस) उनके मूल्य दिखाएगा - अपराधी होगा Nothing

IDE debug display

आपको प्रासंगिक कोड से किसी भी कोशिश / कैच ब्लॉक को भी हटा देना चाहिए, खासतौर पर ऐसे लोग जहां कैच ब्लॉक में कुछ भी नहीं है। इससे आपके ऑब्जेक्ट का उपयोग करने का प्रयास करने पर आपका कोड क्रैश हो जाएगा Nothingआप यही चाहते हैं क्योंकि यह सटीक की पहचान करेगा स्थान समस्या का, और आपको ऑब्जेक्ट की पहचान करने की अनुमति देता है।

MsgBox कैच में प्रदर्शित करता है Error while... थोड़ी मदद की होगी। यह विधि भी होती है बहुत बुरा स्टैक ओवरफ़्लो प्रश्न, क्योंकि आप वास्तविक अपवाद, वस्तु शामिल या यहां तक ​​कि कोड की रेखा का वर्णन नहीं कर सकते हैं।

आप भी इसका उपयोग कर सकते हैं Locals Window (डीबग -> विंडोज़ -> स्थानीय) अपनी वस्तुओं की जांच करने के लिए।

एक बार जब आप जानते हैं कि समस्या क्या है और कहां है, तो आमतौर पर एक नया प्रश्न पोस्ट करने से ठीक और तेज़ करना काफी आसान होता है।

यह भी देखें:

उदाहरण और उपचार

कक्षा वस्तुओं / एक उदाहरण बनाना

Dim reg As CashRegister
...
TextBox1.Text = reg.Amount         ' NRE

समस्या यह है कि Dim एक CashRegister नहीं बनाता है वस्तु; यह केवल नाम का एक चर घोषित करता है reg उस प्रकार का। घोषणा एक ऑब्जेक्ट वैरिएबल और एक बनाना उदाहरण दो अलग-अलग चीजें हैं।

उपाय

New जब आप इसे घोषित करते हैं तो ऑपरेटर को अक्सर उदाहरण बनाने के लिए उपयोग किया जा सकता है:

Dim reg As New CashRegister        ' [New] creates instance, invokes the constructor

' Longer, more explicit form:
Dim reg As CashRegister = New CashRegister

जब यह बाद में उदाहरण बनाने के लिए उपयुक्त है:

Private reg As CashRegister         ' Declare
  ...
reg = New CashRegister()            ' Create instance

ध्यान दें: ऐसा न करें उपयोग Dim फिर एक प्रक्रिया में, कन्स्ट्रक्टर सहित (Sub New):

Private reg As CashRegister
'...

Public Sub New()
   '...
   Dim reg As New CashRegister
End Sub

यह एक बना देगा स्थानीय चर, reg, जो केवल उस संदर्भ (उप) में मौजूद है। reg मॉड्यूल स्तर के साथ चर Scope जो आप हर जगह उपयोग करेंगे Nothing

गुम है New ऑपरेटर का # 1 कारण है NullReference Exceptions स्टैक ओवरफ़्लो प्रश्नों में देखी गई समीक्षा की गई।

विजुअल बेसिक प्रक्रिया को बार-बार उपयोग करने की कोशिश करता है New: का उपयोग करते हुए New ऑपरेटर एक बनाता है नया वस्तु और कॉल Sub New - कन्स्ट्रक्टर - जहां आपका ऑब्जेक्ट कोई अन्य प्रारंभिक प्रदर्शन कर सकता है।

स्पष्ट होना, Dim (या Private) केवल वाणी एक चर और इसकी Typeक्षेत्र चर के - चाहे वह पूरे मॉड्यूल / कक्षा के लिए मौजूद है या एक प्रक्रिया के लिए स्थानीय है - द्वारा निर्धारित किया जाता है कहा पे यह घोषित किया गया है। Private | Friend | Public पहुंच स्तर को परिभाषित करता है, नहीं क्षेत्र

अधिक जानकारी के लिए देखें:


Arrays

Arrays भी तत्काल होना चाहिए:

Private arr as String()

यह सरणी केवल घोषित की गई है, न बनाई गई है। एक सरणी शुरू करने के कई तरीके हैं:

Private arr as String() = New String(10){}
' or
Private arr() As String = New String(10){}

' For a local array (in a procedure) and using 'Option Infer':
Dim arr = New String(10) {}

नोट: वीएस 2010 के साथ शुरुआत, जब एक शाब्दिक और स्थानीय उपयोग से स्थानीय सरणी शुरू करना Option Infer, द As <Type> तथा New तत्व वैकल्पिक हैं:

Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14}
Dim myDbl = New Double() {1.5, 2, 9.9, 18, 3.14}
Dim myDbl() = {1.5, 2, 9.9, 18, 3.14}

डेटा प्रकार और सरणी आकार असाइन किए जा रहे डेटा से अनुमानित हैं। कक्षा / मॉड्यूल स्तर की घोषणाओं की अभी भी आवश्यकता है As <Type> साथ में Option Strict:

Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}

उदाहरण: कक्षा वस्तुओं के ऐरे

Dim arrFoo(5) As Foo

For i As Integer = 0 To arrFoo.Count - 1
   arrFoo(i).Bar = i * 10       ' Exception
Next

सरणी बनाई गई है, लेकिन Fooइसमें वस्तुओं नहीं है।

उपाय

For i As Integer = 0 To arrFoo.Count - 1
    arrFoo(i) = New Foo()         ' Create Foo instance
    arrFoo(i).Bar = i * 10
Next

इसका उपयोग करना List(Of T) वैध वस्तु के बिना तत्व रखना मुश्किल हो जाएगा:

Dim FooList As New List(Of Foo)     ' List created, but it is empty
Dim f As Foo                        ' Temporary variable for the loop

For i As Integer = 0 To 5
    f = New Foo()                    ' Foo instance created
    f.Bar =  i * 10
    FooList.Add(f)                   ' Foo object added to list
Next

अधिक जानकारी के लिए देखें: