मेरे पास कुछ कोड हैं और जब यह निष्पादित होता है, तो यह ए NullReferenceException
, फेंकता है :
वस्तु का संदर्भ वस्तु की आवृत्ति अनुसार सेट नहीं। है।
इसका क्या मतलब है, और मैं इस त्रुटि को ठीक करने के लिए क्या कर सकता हूं?
मेरे पास कुछ कोड हैं और जब यह निष्पादित होता है, तो यह ए NullReferenceException
, फेंकता है :
वस्तु का संदर्भ वस्तु की आवृत्ति अनुसार सेट नहीं। है।
इसका क्या मतलब है, और मैं इस त्रुटि को ठीक करने के लिए क्या कर सकता हूं?
जवाबों:
आप कुछ ऐसा उपयोग करने का प्रयास कर रहे हैं जो null
(या Nothing
VB.NET में है)। इसका मतलब है कि आप इसे करने के लिए तैयार हैंnull
, या आप इसे कभी भी किसी भी चीज़ के लिए सेट नहीं करते हैं।
और कुछ की तरह, null
चारों ओर से गुजर जाता है। अगर ऐसा है null
में विधि 'ए', यह हो सकता है कि विधि "बी" एक पारित कर दिया null
करने के लिए विधि 'ए'।
null
अलग-अलग अर्थ हो सकते हैं:
NullReferenceException
।null
कर रहा है कि कोई सार्थक मूल्य उपलब्ध नहीं है। ध्यान दें कि C # में चर के लिए अशक्त डेटाैटिप्स की अवधारणा है (जैसे डेटाबेस तालिकाओं में अशक्त क्षेत्र हो सकते हैं) - आप 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
।
runtime
फेंक एक 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; }
}
नेस्टेड संग्रह Initializers
समान व्यवहार करता है:
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
। संग्रह Initializer
सिंटैक्स के लिए एक संग्रह नहीं बनाता है 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.
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
}
}
###Bad Naming Conventions:
If you named fields differently from locals, you might have realized that you never initialized the field.
सार्वजनिक वर्ग फॉर्म 1 {निजी ग्राहक ग्राहक;
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!";
}
}
// if the "FirstName" session value has not yet been set,
// then this line will throw a NullReferenceException
string firstName = Session["FirstName"].ToString();
अपवाद तब होता है जब की संपत्ति को संदर्भित तो @Model
एक में ASP.NET MVC View
, आपको यह समझना होगा कि जरूरत है 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;
यह फेंक नहीं करता है, InvalidCastException
लेकिन null
जब कलाकार विफल हो जाता है (और जब someObject
खुद को अशक्त होता है) रिटर्न देता है । तो उस के बारे में पता होना चाहिए।
FirstOrDefault()
औरSingleOrDefault()
सादे संस्करण First()
और Single()
अपवाद कुछ नहीं होने पर फेंक देते हैं। "OrDefault" संस्करण उस स्थिति में अशक्त हो जाते हैं। तो उस के बारे में पता होना चाहिए।
foreach
जब आप अशक्त संग्रह पुनरावृति करने की कोशिश करते हैं तो फेंकता है। आमतौर null
पर संग्रह को वापस करने वाले तरीकों से अप्रत्याशित परिणाम के कारण ।
List<int> list = null;
foreach(var v in list) { } // exception
अधिक यथार्थवादी उदाहरण - XML दस्तावेज़ से नोड्स का चयन करें। अगर नोड्स नहीं मिले तो फेंक देंगे लेकिन शुरुआती डिबगिंग से पता चलता है कि सभी गुण मान्य हैं:
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()
लिए nullable
मूल्य प्रकारों के लिए उपयोग करें 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
??
[C #] या If()
[VB]।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]
सरणियों के लिए (C # 6 और VB.NET 14 में उपलब्ध):इसे कभी-कभी सुरक्षित नेविगेशन या एल्विस (इसके आकार के बाद) ऑपरेटर भी कहा जाता है। यदि ऑपरेटर के बाईं ओर की अभिव्यक्ति शून्य है, तो सही पक्ष का मूल्यांकन नहीं किया जाएगा, और इसके बजाय नल वापस आ गया है। इसका मतलब है कि इस तरह के मामले:
var title = person.Title.ToUpper();
यदि व्यक्ति के पास शीर्षक नहीं है, तो यह एक अपवाद फेंक देगा क्योंकि यह ToUpper
एक शून्य मान के साथ एक संपत्ति पर कॉल करने की कोशिश कर रहा है ।
में C# 5
और नीचे, इस के साथ संरक्षित किया जा सकता है:
var title = person.Title == null ? null : person.Title.ToUpper();
अब शीर्षक चर एक अपवाद को फेंकने के बजाय अशक्त होगा। C # 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];
और i<sup>th</sup>
तत्व को लौटाता है ।
C# 8
वहाँ अशक्त संदर्भ में प्रस्तुत किया गया है और अशक्त संदर्भ प्रकार वैरिएबल पर स्थिर विश्लेषण करते हैं और एक संकलक चेतावनी प्रदान करते हैं यदि मूल्य संभावित रूप से अशक्त हो सकता है या अशक्त करने के लिए सेट किया गया है। अशक्त संदर्भ प्रकार स्पष्ट रूप से अशक्त होने की अनुमति देता है।
अशक्त एनोटेशन संदर्भ और अशक्त चेतावनी संदर्भ Nullable
आपकी csproj
फ़ाइल में तत्व का उपयोग करके किसी प्रोजेक्ट के लिए सेट किया जा सकता है । यह तत्व कॉन्फ़िगर करता है कि कंपाइलर किस प्रकार की अशक्तता की व्याख्या करता है और क्या चेतावनी उत्पन्न करता है। मान्य सेटिंग्स हैं:
एक अशक्त संदर्भ प्रकार को शून्य मान के प्रकार के समान सिंटैक्स का उपयोग करके नोट किया जाता है: एक ?
चर के प्रकार से जोड़ा जाता है।
C#
"इटरेटर ब्लॉक" (कुछ अन्य लोकप्रिय भाषाओं में "जनरेटर") का समर्थन करता है। आस्थगित निष्पादन के कारण इटैलर ब्लॉकों में डिबगिंग अपवाद विशेष रूप से कमजोर हो सकते हैं:
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
ऑब्जेक्ट के लिए संदर्भ स्रोत की जांच करते हैं, तो आप देखेंगे कि इस तकनीक का उपयोग किया जाता है। यह लिखने के लिए थोड़ा अधिक स्पष्ट है, लेकिन यह अशक्तता त्रुटियों को बहुत आसान बना देता है। कॉलर की सुविधा के लिए अपना कोड ऑप्टिमाइज़ करें, न कि लेखक की सुविधा के लिए ।
C#
एक "असुरक्षित" मोड है, जो नाम का अर्थ है, अत्यंत खतरनाक है क्योंकि सामान्य सुरक्षा तंत्र जो स्मृति सुरक्षा और प्रकार की सुरक्षा प्रदान करते हैं, लागू नहीं होते हैं। जब तक आपके पास मेमोरी काम नहीं करती है, तब तक आपको असुरक्षित कोड नहीं लिखना चाहिए ।
असुरक्षित मोड में, आपको दो महत्वपूर्ण तथ्यों की जानकारी होनी चाहिए:
यह समझने के लिए कि यह क्यों है, यह समझने में मदद करता है कि .NET पहली बार में शून्य से अधिक अपवाद कैसे पैदा करता है। (ये विवरण विंडोज़ पर चलने वाले .NET पर लागू होते हैं; अन्य ऑपरेटिंग सिस्टम समान तंत्र का उपयोग करते हैं।)
स्मृति का आभासीकरण किया जाता है Windows
; प्रत्येक प्रक्रिया को मेमोरी के कई "पेज" का वर्चुअल मेमोरी स्पेस मिलता है जो ऑपरेटिंग सिस्टम द्वारा ट्रैक किया जाता है। स्मृति के प्रत्येक पृष्ठ पर झंडे सेट होते हैं जो यह निर्धारित करते हैं कि इसका उपयोग कैसे किया जा सकता है: से पढ़ा, लिखा, निष्पादित किया गया, और इसी तरह। सबसे कम पृष्ठ को "किसी भी तरह से उपयोग किए जाने पर त्रुटि उत्पन्न करना" के रूप में चिह्नित किया गया है।
एक अशक्त सूचक और एक अशक्त संदर्भ दोनों C#
को आंतरिक रूप से संख्या शून्य के रूप में दर्शाया जाता है, और इसलिए इसे अपने संबंधित मेमोरी स्टोरेज में डेरेफेर करने का कोई भी प्रयास ऑपरेटिंग सिस्टम को त्रुटि उत्पन्न करने का कारण बनता है। .NET रनटाइम तब इस त्रुटि का पता लगाता है और इसे अशक्तता अपवाद में बदल देता है।
यही कारण है कि दोनों एक अशक्त सूचक और एक शून्य संदर्भ दोनों को एक ही अपवाद पैदा करता है।
दूसरे बिंदु के बारे में क्या? वर्चुअल मेमोरी के सबसे निचले पेज में आने वाले किसी भी अवैध पॉइंटर को डीरेफर करने से एक ही ऑपरेटिंग सिस्टम एरर होता है, और इस तरह एक ही अपवाद होता है।
यह क्यों समझ में आता है? ठीक है, मान लें कि हमारे पास एक संरचना है जिसमें दो ints, और एक अशक्त सूचक शून्य के बराबर है। यदि हम संरचना में दूसरे इंट को दखल देने का CLR
प्रयास करते हैं, तो स्थान शून्य पर भंडारण का उपयोग करने का प्रयास नहीं करेंगे; यह स्टोरेज को स्थान चार पर पहुँचा देगा। लेकिन तार्किक रूप से यह एक अशांति है क्योंकि हम अशक्त के माध्यम से उस पते पर जा रहे हैं ।
यदि आप असुरक्षित कोड के साथ काम कर रहे हैं और आपको एक अशक्त अपवाद मिल रहा है, तो बस इस बात से अवगत रहें कि अपमानजनक सूचक को शून्य होने की आवश्यकता नहीं है। यह निम्नतम पृष्ठ में कोई भी स्थान हो सकता है, और यह अपवाद उत्पन्न होगा।
new Book { Author = { Age = 45 } };
भीतर का इनिशियलाइज़ेशन भी कैसे होता है ... मैं ऐसी स्थिति के बारे में नहीं सोच सकता, जहाँ भीतर का काम कभी चलेगा, फिर भी यह काम करता है और अंतर्मुखी काम करता है ... जब तक कि यह संरचना के लिए न हो?
NullReference Exception
के लिए दृश्य मूल में एक से अलग नहीं है सी # । आखिरकार, वे दोनों .NET फ्रेमवर्क में परिभाषित एक ही अपवाद को रिपोर्ट कर रहे हैं जो वे दोनों का उपयोग करते हैं। Visual Basic के लिए अद्वितीय कारण दुर्लभ हैं (शायद केवल एक)।
यह उत्तर विज़ुअल बेसिक शब्दों, सिंटैक्स और संदर्भ का उपयोग करेगा। उपयोग किए जाने वाले उदाहरण ढेर सारे स्टैक ओवरफ्लो प्रश्नों से आते हैं। यह अक्सर पोस्ट में देखी जाने वाली स्थितियों के प्रकार का उपयोग करके प्रासंगिकता को अधिकतम करना है । उन लोगों के लिए थोड़ा और स्पष्टीकरण भी प्रदान किया जाता है जिन्हें इसकी आवश्यकता हो सकती है। आपके जैसा एक उदाहरण यहाँ बहुत संभावना है।
ध्यान दें:
NullReferenceException
(एनआरई), इसे कैसे खोजना है, इसे कैसे ठीक करना है और कैसे इससे बचना है। एक एनआरई कई तरीकों से हो सकता है इसलिए यह आपके एकमात्र मुठभेड़ होने की संभावना नहीं है।संदेश "ऑब्जेक्ट ऑब्जेक्ट के एक उदाहरण के लिए सेट नहीं है" का अर्थ है कि आप उस ऑब्जेक्ट का उपयोग करने की कोशिश कर रहे हैं जिसे प्रारंभ नहीं किया गया है। यह इनमें से एक को उबालता है:
चूंकि समस्या एक वस्तु संदर्भ है Nothing
, जो है , इसका उत्तर यह है कि उन्हें यह पता लगाने के लिए कि कौन सा है। फिर निर्धारित करें कि यह क्यों प्रारंभिक नहीं है। विभिन्न चर पर माउस को पकड़ें और विजुअल स्टूडियो (वीएस) अपने मूल्यों को दिखाएगा - अपराधी होगा Nothing
।
आपको संबंधित कोड से किसी भी कोशिश / कैच ब्लॉक को भी हटा देना चाहिए, खासकर उन लोगों को जहां कैच ब्लॉक में कुछ भी नहीं है। जब यह किसी ऑब्जेक्ट का उपयोग करने का प्रयास करता है तो यह आपके कोड को क्रैश कर देगा Nothing
। यह वही है जो आप चाहते हैं क्योंकि यह समस्या के सटीक स्थान की पहचान करेगा , और आपको इसके कारण होने वाली वस्तु की पहचान करने की अनुमति देगा।
MsgBox
पकड़ में A जो प्रदर्शित करता है उससे 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
ऑपरेटर को मिस करनाNullReference Exceptions
स्टैक ओवरफ्लो प्रश्नों की समीक्षा में देखा गया # 1 कारण है ।Visual Basic का उपयोग करके प्रक्रिया को बार-बार स्पष्ट करने की कोशिश करता है
New
:New
ऑपरेटर का उपयोग करना एक बनाता है नई वस्तु बनती है और कॉल होती हैSub New
- निर्माणकर्ता - जहाँ आपकी वस्तु किसी अन्य इनिशियलाइज़ेशन को कर सकती है।
स्पष्ट होने के लिए, Dim
(या Private
) केवल एक चर और इसकी घोषणा करता है Type
। चर का दायरा - चाहे वह पूरे मॉड्यूल / वर्ग के लिए मौजूद हो या प्रक्रिया के लिए स्थानीय हो - द्वारा निर्धारित किया जाता है कि यह कहां घोषित किया गया है। Private | Friend | Public
पहुँच स्तर को परिभाषित करता है, स्कोप को नहीं ।
अधिक जानकारी के लिए देखें:
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
अधिक जानकारी के लिए देखें:
.NET संग्रह (जिनमें से कई किस्में हैं - सूची, शब्दकोश, आदि) को भी तत्काल या बनाया जाना चाहिए।
Private myList As List(Of String)
..
myList.Add("ziggy") ' NullReference
आपको एक ही कारण के लिए एक ही अपवाद मिलता है - myList
केवल घोषित किया गया था, लेकिन कोई उदाहरण नहीं बनाया गया। उपाय एक ही है:
myList = New List(Of String)
' Or create an instance when declared:
Private myList As New List(Of String)
एक सामान्य निरीक्षण एक वर्ग है जो एक संग्रह का उपयोग करता है Type
:
Public Class Foo
Private barList As List(Of Bar)
Friend Function BarCount As Integer
Return barList.Count
End Function
Friend Sub AddItem(newBar As Bar)
If barList.Contains(newBar) = False Then
barList.Add(newBar)
End If
End Function
या तो प्रक्रिया एक एनआरई में परिणाम करेगी, क्योंकि barList
केवल घोषित की जाती है, तात्कालिक नहीं। का एक उदाहरण Foo
बनाने से भी आंतरिक का एक उदाहरण नहीं होगा barList
। कंस्ट्रक्टर में ऐसा करने का इरादा हो सकता है:
Public Sub New ' Constructor
' Stuff to do when a new Foo is created...
barList = New List(Of Bar)
End Sub
पहले की तरह, यह गलत है:
Public Sub New()
' Creates another barList local to this procedure
Dim barList As New List(Of Bar)
End Sub
अधिक जानकारी के लिए, List(Of T)
क्लास देखें ।
डेटाबेस प्रस्तुत के साथ एक NullReference के लिए कई अवसर कार्य क्योंकि वहाँ कई वस्तुओं (हो सकता है Command
, Connection
, Transaction
, Dataset
, DataTable
, DataRows
एक ही बार में ....) उपयोग में। नोट: यह कोई फर्क नहीं पड़ता कि आप किस डेटा प्रदाता का उपयोग कर रहे हैं - MySQL, SQL सर्वर, OleDB, आदि - अवधारणाएं समान हैं।
उदाहरण 1
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows As Integer
con.Open()
Dim sql = "SELECT * FROM tblfoobar_List"
da = New OleDbDataAdapter(sql, con)
da.Fill(ds, "foobar")
con.Close()
MaxRows = ds.Tables("foobar").Rows.Count ' Error
पहले की तरह, ds
डेटासेट ऑब्जेक्ट घोषित किया गया था, लेकिन एक उदाहरण कभी नहीं बनाया गया था। DataAdapter
एक मौजूदा भर जाएगा DataSet
, नहीं एक बनाएँ। इस मामले में, चूंकि ds
एक स्थानीय चर है, आईडीई आपको चेतावनी देता है कि ऐसा हो सकता है:
जब मॉड्यूल / वर्ग स्तर के चर के रूप में घोषित किया जाता है, जैसा कि मामला प्रतीत होता है con
, तो कंपाइलर को पता नहीं चल सकता है कि ऑब्जेक्ट अपस्ट्रीम प्रक्रिया द्वारा बनाया गया था या नहीं। चेतावनियों को नजरअंदाज न करें।
उपाय
Dim ds As New DataSet
उदाहरण 2
ds = New DataSet
da = New OleDBDataAdapter(sql, con)
da.Fill(ds, "Employees")
txtID.Text = ds.Tables("Employee").Rows(0).Item(1)
txtID.Name = ds.Tables("Employee").Rows(0).Item(2)
एक टाइपो यहाँ एक समस्या है: Employees
बनाम Employee
। कोई DataTable
"कर्मचारी" नहीं बनाया गया था, इसलिए NullReferenceException
इसके उपयोग की कोशिश करने वाले परिणाम। एक अन्य संभावित समस्या यह मानकर चल रही है कि Items
ऐसा तब नहीं होगा जब SQL में WHERE क्लॉज शामिल हो।
उपाय
चूंकि यह एक तालिका का उपयोग करता है, इसलिए Tables(0)
स्पेलिंग त्रुटियों से बचना होगा। जांच से Rows.Count
भी मदद मिल सकती है:
If ds.Tables(0).Rows.Count > 0 Then
txtID.Text = ds.Tables(0).Rows(0).Item(1)
txtID.Name = ds.Tables(0).Rows(0).Item(2)
End If
Fill
एक ऐसा कार्य है Rows
जो प्रभावितों की संख्या को लौटाता है जिसे परीक्षण भी किया जा सकता है:
If da.Fill(ds, "Employees") > 0 Then...
उदाहरण 3
Dim da As New OleDb.OleDbDataAdapter("SELECT TICKET.TICKET_NO,
TICKET.CUSTOMER_ID, ... FROM TICKET_RESERVATION AS TICKET INNER JOIN
FLIGHT_DETAILS AS FLIGHT ... WHERE [TICKET.TICKET_NO]= ...", con)
Dim ds As New DataSet
da.Fill(ds)
If ds.Tables("TICKET_RESERVATION").Rows.Count > 0 Then
DataAdapter
प्रदान करेगा TableNames
जैसा कि पिछले उदाहरण में दिखाया गया है, लेकिन यह एसक्यूएल या डेटाबेस तालिका से नहीं है पार्स नाम। नतीजतन,ds.Tables("TICKET_RESERVATION")
एक गैर-मौजूद तालिका का संदर्भ देता है।
उपचार ही है, सूचकांक द्वारा तालिका को देख:
If ds.Tables(0).Rows.Count > 0 Then
डेटाटेबल क्लास भी देखें ।
If myFoo.Bar.Items IsNot Nothing Then
...
कोड केवल परीक्षण कर रहा है Items
जबकि दोनों myFoo
और Bar
कुछ भी नहीं हो सकता है। उपाय एक बार में पूरी श्रृंखला या वस्तुओं में से एक का पथ का परीक्षण करने के लिए है:
If (myFoo IsNot Nothing) AndAlso
(myFoo.Bar IsNot Nothing) AndAlso
(myFoo.Bar.Items IsNot Nothing) Then
....
AndAlso
महत्वपूर्ण है। पहली False
स्थिति सामने आने के बाद बाद के परीक्षण नहीं किए जाएंगे । यह कोड को एक बार में ऑब्जेक्ट (ओं) में सुरक्षित रूप से 'ड्रिल' करने की अनुमति देता है, myFoo.Bar
केवल (और अगर) के मूल्यांकन के बाद ही myFoo
मान्य होता है। जटिल ऑब्जेक्ट्स को कोड करते समय ऑब्जेक्ट चेन या पाथ काफी लंबा मिल सकता है:
myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")
किसी null
वस्तु के 'डाउनस्ट्रीम' को संदर्भित करना संभव नहीं है । यह नियंत्रणों पर भी लागू होता है:
myWebBrowser.Document.GetElementById("formfld1").InnerText = "some value"
यहाँ, myWebBrowser
या Document
कुछ भी नहीं हो सकता है या formfld1
तत्व मौजूद नहीं हो सकता है।
Dim cmd5 As New SqlCommand("select Cartons, Pieces, Foobar " _
& "FROM Invoice where invoice_no = '" & _
Me.ComboBox5.SelectedItem.ToString.Trim & "' And category = '" & _
Me.ListBox1.SelectedItem.ToString.Trim & "' And item_name = '" & _
Me.ComboBox2.SelectedValue.ToString.Trim & "' And expiry_date = '" & _
Me.expiry.Text & "'", con)
अन्य बातों के अलावा, यह कोड यह अनुमान नहीं लगाता है कि उपयोगकर्ता ने एक या अधिक यूआई नियंत्रण में कुछ का चयन नहीं किया होगा। ListBox1.SelectedItem
अच्छी तरह से हो सकता है Nothing
, इसलिए ListBox1.SelectedItem.ToString
एक एनआरई में परिणाम होगा।
उपाय
उपयोग करने से पहले डेटा को मान्य करें (उपयोग Option Strict
और SQL पैरामीटर भी):
Dim expiry As DateTime ' for text date validation
If (ComboBox5.SelectedItems.Count > 0) AndAlso
(ListBox1.SelectedItems.Count > 0) AndAlso
(ComboBox2.SelectedItems.Count > 0) AndAlso
(DateTime.TryParse(expiry.Text, expiry) Then
'... do stuff
Else
MessageBox.Show(...error message...)
End If
वैकल्पिक रूप से, आप उपयोग कर सकते हैं (ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Public Class Form1
Private NameBoxes = New TextBox(5) {Controls("TextBox1"), _
Controls("TextBox2"), Controls("TextBox3"), _
Controls("TextBox4"), Controls("TextBox5"), _
Controls("TextBox6")}
' same thing in a different format:
Private boxList As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}
' Immediate NRE:
Private somevar As String = Me.Controls("TextBox1").Text
यह एनआरई पाने का एक काफी सामान्य तरीका है। C # में, यह कैसे कोडित है, इसके आधार पर, IDE रिपोर्ट करेगा Controls
जो वर्तमान संदर्भ में मौजूद नहीं है, या "गैर-स्थिर सदस्य का संदर्भ नहीं दे सकता है"। तो, कुछ हद तक, यह एक VB- केवल स्थिति है। यह भी जटिल है क्योंकि यह एक विफलता कैस्केड के परिणामस्वरूप हो सकता है।
सरणियों और संग्रह को इस तरह से आरंभ नहीं किया जा सकता है। यह इनिशियलाइज़ेशन कोड कंस्ट्रक्टर या बनाने से पहले चलेगा । नतीजतन:Form
Controls
somevar
काम एक तत्काल एनआरई में परिणाम होगा क्योंकि कुछ भी नहीं है एक भी नहीं है .Text
संपत्तिबाद में सरणी तत्वों को संदर्भित करने से NRE हो जाएगा। यदि आप ऐसा करते हैं Form_Load
, तो एक विषम बग के कारण, IDE अपवाद तब नहीं हो सकता जब यह होता है। जब आपका कोड सरणी का उपयोग करने का प्रयास करता है तो अपवाद बाद में पॉप जाएगा । यह "मूक अपवाद" इस पोस्ट में विस्तृत है । हमारे उद्देश्यों के लिए, कुंजी यह है कि जब एक फॉर्म ( Sub New
या Form Load
ईवेंट) बनाते समय कुछ भयावह होता है , तो अपवाद अप्रमाणित हो सकते हैं, कोड प्रक्रिया से बाहर निकलता है और बस फॉर्म प्रदर्शित करता है।
चूंकि एनआरई के बाद आपके Sub New
या Form Load
ईवेंट में कोई अन्य कोड नहीं चलेगा, इसलिए बहुत सी अन्य चीजों को अनइंस्टॉल किया जा सकता है।
Sub Form_Load(..._
'...
Dim name As String = NameBoxes(2).Text ' NRE
' ...
' More code (which will likely not be executed)
' ...
End Sub
ध्यान दें कि यह किसी भी और सभी नियंत्रण और घटक संदर्भों पर लागू होता है, जहां ये अवैध हैं:
Public Class Form1
Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
Private studentName As String = TextBox13.Text
आंशिक उपाय
यह उत्सुक है कि वीबी एक चेतावनी प्रदान नहीं करता है, लेकिन उपाय कंटेनरों को फॉर्म स्तर पर घोषित करना है, लेकिन नियंत्रण के मौजूद होने पर उन्हें लोड लोड ईवेंट हैंडलर में आरंभ करना है। यह तब तक किया जा सकता है Sub New
जब तक आपका कोड InitializeComponent
कॉल के बाद है :
' Module level declaration
Private NameBoxes as TextBox()
Private studentName As String
' Form Load, Form Shown or Sub New:
'
' Using the OP's approach (illegal using OPTION STRICT)
NameBoxes = New TextBox() {Me.Controls("TextBox1"), Me.Controls("TestBox2"), ...)
studentName = TextBox32.Text ' For simple control references
सरणी कोड अभी तक जंगल से बाहर नहीं हो सकता है। कोई भी नियंत्रण जो कंटेनर नियंत्रण में है (जैसे GroupBox
या Panel
) में नहीं मिलेगा Me.Controls
; वे उस पैनल या GroupBox के नियंत्रण संग्रह में होंगे। जब नियंत्रण नाम गलत वर्तनी ( "TeStBox2"
) है, तो कोई नियंत्रण वापस नहीं किया जाएगा । ऐसे मामलों में, Nothing
फिर से उन सरणी तत्वों में संग्रहीत किया जाएगा और जब आप इसे संदर्भित करने का प्रयास करेंगे तो एक एनआरई परिणाम देगा।
इन्हें ढूंढना आसान होना चाहिए ताकि आप जान सकें कि आप क्या देख रहे हैं:
"Button2" एक पर रहता है Panel
उपाय
प्रपत्र के Controls
संग्रह का उपयोग करके नाम के अप्रत्यक्ष संदर्भों के बजाय , नियंत्रण संदर्भ का उपयोग करें:
' Declaration
Private NameBoxes As TextBox()
' Initialization - simple and easy to read, hard to botch:
NameBoxes = New TextBox() {TextBox1, TextBox2, ...)
' Initialize a List
NamesList = New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})
' or
NamesList = New List(Of TextBox)
NamesList.AddRange({TextBox1, TextBox2, TextBox3...})
Private bars As New List(Of Bars) ' Declared and created
Public Function BarList() As List(Of Bars)
bars.Clear
If someCondition Then
For n As Integer = 0 to someValue
bars.Add(GetBar(n))
Next n
Else
Exit Function
End If
Return bars
End Function
यह एक ऐसा मामला है जहां आईडीई आपको चेतावनी देगा कि ' सभी रास्तों का एक मूल्य और एक NullReferenceException
परिणाम नहीं हो सकता है '। आप चेतावनी को दबा सकते हैं, के Exit Function
साथ प्रतिस्थापित करके Return Nothing
, लेकिन यह समस्या का समाधान नहीं करता है। कुछ भी जो someCondition = False
एनआरई में परिणाम देगा जब वापसी का उपयोग करने की कोशिश करता है :
bList = myFoo.BarList()
For Each b As Bar in bList ' EXCEPTION
...
उपाय
के Exit Function
साथ फ़ंक्शन में बदलें Return bList
। खाली लौटना List
वैसा ही नहीं है जैसा लौटना Nothing
। यदि एक मौका है कि एक लौटी हुई वस्तु हो सकती है Nothing
, तो उपयोग करने से पहले परीक्षण करें:
bList = myFoo.BarList()
If bList IsNot Nothing Then...
एक बुरी तरह से कार्यान्वित किया गया प्रयास / कैच छिपा सकता है जहां समस्या है और नए परिणाम हैं:
Dim dr As SqlDataReader
Try
Dim lnk As LinkButton = TryCast(sender, LinkButton)
Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow)
Dim eid As String = GridView1.DataKeys(gr.RowIndex).Value.ToString()
ViewState("username") = eid
sqlQry = "select FirstName, Surname, DepartmentName, ExtensionName, jobTitle,
Pager, mailaddress, from employees1 where username='" & eid & "'"
If connection.State <> ConnectionState.Open Then
connection.Open()
End If
command = New SqlCommand(sqlQry, connection)
'More code fooing and barring
dr = command.ExecuteReader()
If dr.Read() Then
lblFirstName.Text = Convert.ToString(dr("FirstName"))
...
End If
mpe.Show()
Catch
Finally
command.Dispose()
dr.Close() ' <-- NRE
connection.Close()
End Try
यह एक ऐसी वस्तु का मामला है जिसे अपेक्षित रूप से नहीं बनाया जा रहा है, लेकिन यह खाली की काउंटर उपयोगिता को भी प्रदर्शित करता है Catch
।
SQL में एक अतिरिक्त अल्पविराम है ('mailaddress' के बाद) जिसके परिणामस्वरूप इसका अपवाद है .ExecuteReader
। बाद Catch
कुछ नहीं करता, Finally
स्वच्छ ऊपर प्रदर्शन करने की कोशिश करता है, लेकिन जब से तुम नहीं कर सकते हैं Close
एक अशक्त DataReader
वस्तु, एक नया NullReferenceException
परिणाम नहीं।
एक खाली Catch
ब्लॉक शैतान का खेल का मैदान है। इस ओपी को चकित किया गया कि वह Finally
ब्लॉक में एनआरई क्यों बन रहा है । अन्य स्थितियों में, एक खाली Catch
चीज के परिणामस्वरूप कुछ और बहाव हो सकता है और आप समस्या के लिए गलत जगह पर गलत चीजों को देखने में समय व्यतीत कर सकते हैं। (ऊपर वर्णित "मूक अपवाद" वही मनोरंजन मूल्य प्रदान करता है।)
उपाय
खाली का उपयोग न करें कोशिश करें / पकड़ ब्लॉक - कोड को क्रैश होने दें ताकि आप ए) कारण की पहचान कर सकें बी) स्थान की पहचान करें और सी) एक उचित उपाय लागू करें। डेवलपर को पकड़ने के लिए प्रयास / कैच ब्लॉक का उद्देश्य विशिष्ट रूप से योग्य व्यक्ति से अपवादों को छिपाना नहीं है।
For Each row As DataGridViewRow In dgvPlanning.Rows
If Not IsDBNull(row.Cells(0).Value) Then
...
IsDBNull
समारोह परीक्षण करने के लिए इस्तेमाल करता है, तो एक है मूल्य के बराबर होती है System.DBNull
: MSDN से:
System.DBNull मान इंगित करता है कि ऑब्जेक्ट गुम या गैर-मौजूद डेटा का प्रतिनिधित्व करता है। DBNull कुछ भी नहीं के समान नहीं है, जो इंगित करता है कि एक चर अभी तक आरंभ नहीं किया गया है।
उपाय
If row.Cells(0) IsNot Nothing Then ...
पहले की तरह, आप कुछ भी नहीं के लिए परीक्षण कर सकते हैं, फिर एक विशिष्ट मूल्य के लिए:
If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then
उदाहरण 2
Dim getFoo = (From f In dbContext.FooBars
Where f.something = something
Select f).FirstOrDefault
If Not IsDBNull(getFoo) Then
If IsDBNull(getFoo.user_id) Then
txtFirst.Text = getFoo.first_name
Else
...
FirstOrDefault
पहला आइटम या डिफ़ॉल्ट मान लौटाता है, जो Nothing
संदर्भ प्रकारों के लिए है और कभी नहीं DBNull
:
If getFoo IsNot Nothing Then...
Dim chk As CheckBox
chk = CType(Me.Controls(chkName), CheckBox)
If chk.Checked Then
Return chk
End If
एक तो CheckBox
साथ chkName
नहीं पाया जा सकता है (या एक में मौजूद है GroupBox
), तो chk
कुछ भी नहीं किया जाएगा और किसी भी संपत्ति एक अपवाद में परिणाम होगा संदर्भित करने के लिए कोशिश कर रहे होंगे।
उपाय
If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...
डीजीवी में समय-समय पर कुछ क्विर्क देखे जाते हैं:
dgvBooks.DataSource = loan.Books
dgvBooks.Columns("ISBN").Visible = True ' NullReferenceException
dgvBooks.Columns("Title").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Author").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Price").DefaultCellStyle.Format = "C"
यदि dgvBooks
है AutoGenerateColumns = True
, तो यह कॉलम बनाएगा, लेकिन यह उन्हें नाम नहीं देता है, इसलिए जब यह उन्हें नाम से संदर्भित करता है तो उपरोक्त कोड विफल हो जाता है।
उपाय
स्तंभों को मैन्युअल रूप से नाम दें, या इंडेक्स द्वारा संदर्भ:
dgvBooks.Columns(0).Visible = True
xlWorkSheet = xlWorkBook.Sheets("sheet1")
For i = 0 To myDGV.RowCount - 1
For j = 0 To myDGV.ColumnCount - 1
For k As Integer = 1 To myDGV.Columns.Count
xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText
xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString()
Next
Next
Next
अपने जब DataGridView
है AllowUserToAddRows
के रूप में True
(डिफ़ॉल्ट), Cells
खाली में / तल पर नई पंक्ति में शामिल होंगे सभी Nothing
। सामग्री (उदाहरण के लिए ToString
) का उपयोग करने के अधिकांश प्रयासों का परिणाम एक एनआरई होगा।
उपाय
एक For/Each
लूप का उपयोग करें और IsNewRow
यह निर्धारित करने के लिए संपत्ति का परीक्षण करें कि क्या यह अंतिम पंक्ति है। यह काम करता AllowUserToAddRows
है या नहीं यह सच है:
For Each r As DataGridViewRow in myDGV.Rows
If r.IsNewRow = False Then
' ok to use this row
यदि आप For n
लूप का उपयोग करते हैं , तो पंक्ति गणना को संशोधित करें या सही Exit For
होने पर उपयोग करें IsNewRow
।
कुछ परिस्थितियों में, उस आइटम का उपयोग करने की कोशिश करना My.Settings
जिससे कोई StringCollection
परिणाम हो सकता है कि आप इसका उपयोग करने वाले पहली बार NullReference में परिणाम कर सकते हैं। समाधान समान है, लेकिन स्पष्ट नहीं है। विचार करें:
My.Settings.FooBars.Add("ziggy") ' foobars is a string collection
चूँकि VB आपके लिए सेटिंग्स का प्रबंधन कर रहा है, इसलिए संग्रह को शुरू करने की अपेक्षा करना उचित है। यह होगा, लेकिन केवल अगर आपने पहले संग्रह में एक प्रारंभिक प्रविष्टि (सेटिंग्स संपादक में) जोड़ दी है। चूँकि जब आइटम जोड़ा जाता है तो संग्रह (जाहिरा तौर पर) इनिशियलाइज़ होता है, यह Nothing
तब रहता है जब सेटिंग्स एडिटर में कोई आइटम जोड़ने के लिए नहीं होते हैं।
उपाय
प्रपत्र के Load
इवेंट हैंडलर में सेटिंग्स संग्रह को आरम्भ करें, यदि / जब जरूरत हो:
If My.Settings.FooBars Is Nothing Then
My.Settings.FooBars = New System.Collections.Specialized.StringCollection
End If
आमतौर पर, Settings
संग्रह को केवल पहली बार शुरू करने की आवश्यकता होगी जब आवेदन चलता है। एक वैकल्पिक उपाय परियोजना में अपने संग्रह के लिए एक प्रारंभिक मूल्य जोड़ना है -> सेटिंग्स | FooBars , प्रोजेक्ट सहेजें, फिर नकली मान निकालें।
आप शायद New
ऑपरेटर को भूल गए ।
या
आपके द्वारा ग्रहण की गई किसी वस्तु को आपके कोड के लिए एक इनिशियलाइज़्ड ऑब्जेक्ट वापस करने के लिए निर्दोष प्रदर्शन करेगा।
संकलक चेतावनी (कभी) और उपयोग Option Strict On
(हमेशा) को अनदेखा न करें ।
एक अन्य परिदृश्य तब होता है जब आप एक अशक्त वस्तु को एक मूल्य प्रकार में डालते हैं । उदाहरण के लिए, नीचे दिया गया कोड:
object o = null;
DateTime d = (DateTime)o;
यह NullReferenceException
डाली पर फेंक देगा । उपरोक्त नमूने में यह काफी स्पष्ट प्रतीत होता है, लेकिन यह अधिक "लेट-बाइंडिंग" जटिल परिदृश्यों में हो सकता है जहां शून्य ऑब्जेक्ट को कुछ कोड से वापस कर दिया गया है जो आपके पास नहीं है, और कास्ट कुछ स्वचालित सिस्टम द्वारा उत्पन्न उदाहरण के लिए है।
इसका एक उदाहरण कैलेंडर नियंत्रण के साथ यह सरल ASP.NET बाइंडिंग टुकड़ा है:
<asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" />
यहां, SelectedDate
वास्तव में एक संपत्ति है - DateTime
प्रकार की - Calendar
वेब नियंत्रण प्रकार की, और बाइंडिंग पूरी तरह से कुछ अशक्त लौटा सकती है। अंतर्निहित ASP.NET जनरेटर कोड का एक टुकड़ा बनाएगा जो ऊपर दिए गए कास्ट कोड के बराबर होगा। और यह एक जगह उठाना NullReferenceException
काफी मुश्किल होगा, क्योंकि यह ASP.NET जनरेट कोड में निहित है जो ठीक संकलित करता है ...
DateTime x = (DateTime) o as DateTime? ?? defaultValue;
इसका मतलब है कि प्रश्न में चर कुछ भी नहीं में बताया गया है। मैं इसे इस तरह उत्पन्न कर सकता था:
SqlConnection connection = null;
connection.Open();
यह त्रुटि को फेंक देगा क्योंकि जब मैंने चर " connection
" घोषित किया है , तो यह कुछ भी इंगित नहीं किया गया है। जब मैं सदस्य को " Open
" कॉल करने का प्रयास करता हूं , तो इसके समाधान के लिए कोई संदर्भ नहीं है, और यह त्रुटि को फेंक देगा।
इस त्रुटि से बचने के लिए:
object == null
।JetBrains का Resharper टूल आपके कोड की हर उस जगह की पहचान करेगा, जिसमें एक नल रेफरेंस एरर की संभावना है, जिससे आप एक नल चेक में डाल सकते हैं। यह त्रुटि बग का नंबर एक स्रोत है, IMHO।
इसका मतलब है कि आपके कोड ने ऑब्जेक्ट रेफरेंस वैरिएबल का उपयोग किया है जो शून्य पर सेट किया गया था (यानी यह एक वास्तविक ऑब्जेक्ट उदाहरण नहीं था)।
त्रुटि को रोकने के लिए, जिन वस्तुओं को अशक्त किया जा सकता है, उनका उपयोग करने से पहले अशक्त के लिए परीक्षण किया जाना चाहिए।
if (myvar != null)
{
// Go ahead and use myvar
myvar.property = ...
}
else
{
// Whoops! myvar is null and cannot be used without first
// assigning it to an instance reference
// Attempting to use myvar here will result in NullReferenceException
}
ध्यान रखें कि परिदृश्य की परवाह किए बिना, कारण हमेशा .NET में समान होता है:
आप एक संदर्भ चर का उपयोग करने का प्रयास कर रहे हैं जिसका मान
Nothing
/ हैnull
। जब मूल्य हैNothing
/null
संदर्भ चर के लिए , तो इसका मतलब है कि यह वास्तव में ढेर पर मौजूद किसी भी वस्तु के उदाहरण के संदर्भ में नहीं है।आपने या तो चर को कुछ भी नहीं सौंपा है, चर के लिए दिए गए मान का कोई उदाहरण कभी नहीं बनाया है, या आपने चर को बराबर
Nothing
/null
मैन्युअल रूप से सेट किया है , या आपने एक फ़ंक्शन कहा है जो चर को आपके लिएNothing
/ सेट करता हैnull
।
फेंके जा रहे इस अपवाद का एक उदाहरण है: जब आप किसी चीज़ की जाँच करने की कोशिश कर रहे हैं, तो यह अशक्त है।
उदाहरण के लिए:
string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)
if (testString.Length == 0) // Throws a nullreferenceexception
{
//Do something
}
.NET रनटाइम एक NullReferenceException को फेंक देगा, जब आप किसी ऐसी चीज पर कार्रवाई करने का प्रयास करते हैं, जो त्वरित नहीं है अर्थात ऊपर कोड।
एक ArgumentNullException की तुलना में जो आमतौर पर एक रक्षात्मक उपाय के रूप में फेंक दी जाती है यदि कोई विधि यह उम्मीद करती है कि जो उसे पारित किया जा रहा है वह शून्य नहीं है।
अधिक जानकारी C # NullReferenceException और Null Parameter में है ।
अद्यतन C # 8.0, 2019: अशक्त संदर्भ प्रकार
C # 8.0 अशक्त संदर्भ प्रकारों और गैर-अशक्त संदर्भ प्रकारों का परिचय देता है । तो केवल अशक्त संदर्भ प्रकारों को NullReferenceException से बचने के लिए जाँच की जानी चाहिए ।
यदि आपने एक संदर्भ प्रकार को इनिशियलाइज़ नहीं किया है, और आप इसके किसी गुण को सेट या पढ़ना चाहते हैं, तो यह NullReetException को फेंक देगा ।
उदाहरण:
Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.
यदि वेरिएबल शून्य नहीं है, तो आप बस जाँच करके इससे बच सकते हैं:
Person p = null;
if (p!=null)
{
p.Name = "Harry"; // Not going to run to this point
}
यह समझने के लिए कि NullReferenceException को क्यों फेंका गया है, मूल्य प्रकार और [संदर्भ प्रकार] [3] के बीच अंतर को जानना महत्वपूर्ण है ।
इसलिए, यदि आप मान प्रकार के साथ काम कर रहे हैं, तो NullReferenceException नहीं हो सकती है। हालांकि आपको संदर्भ प्रकारों से निपटने के दौरान सतर्क रहने की आवश्यकता है !
केवल संदर्भ प्रकार, जैसा कि नाम से पता चल रहा है, संदर्भ या बिंदु को शाब्दिक रूप से कुछ भी नहीं (या 'अशक्त') रख सकते हैं। जबकि मूल्य प्रकारों में हमेशा एक मूल्य होता है।
संदर्भ प्रकार (इन लोगों की जांच होनी चाहिए):
मूल्य प्रकार (आप केवल इन लोगों को अनदेखा कर सकते हैं):
एक और मामला जहां NullReferenceExceptions
हो सकता है वह as
ऑपरेटर का गलत (गलत) उपयोग है :
class Book {
public string Name { get; set; }
}
class Car { }
Car mycar = new Car();
Book mybook = mycar as Book; // Incompatible conversion --> mybook = null
Console.WriteLine(mybook.Name); // NullReferenceException
यहाँ, Book
और Car
असंगत प्रकार हैं; एक में Car
परिवर्तित नहीं किया जा सकता है / कास्ट Book
। जब यह कलाकार विफल हो जाता है, तो as
रिटर्न करता है null
। इसके mybook
बाद उपयोग करने से एNullReferenceException
।
सामान्य तौर पर, आपको एक कास्ट का उपयोग करना चाहिए या as
, निम्नानुसार करना चाहिए :
यदि आप टाइप रूपांतरण की अपेक्षा कर रहे हैं कि आप हमेशा सफल रहें (यानी आप जानते हैं कि समय से पहले वस्तु क्या होनी चाहिए), तो आपको एक भुगतान करना चाहिए:
ComicBook cb = (ComicBook)specificBook;
यदि आप प्रकार के अनिश्चित हैं, लेकिन आप इसे एक विशिष्ट प्रकार के रूप में उपयोग करने का प्रयास करना चाहते हैं , तो उपयोग करें as
:
ComicBook cb = specificBook as ComicBook;
if (cb != null) {
// ...
}
आप ऑब्जेक्ट का उपयोग कर रहे हैं जिसमें शून्य मान संदर्भ है। तो यह एक शून्य अपवाद दे रहा है। उदाहरण में स्ट्रिंग मान शून्य है और इसकी लंबाई की जाँच करते समय, अपवाद हुआ।
उदाहरण:
string value = null;
if (value.Length == 0) // <-- Causes exception
{
Console.WriteLine(value); // <-- Never reached
}
अपवाद त्रुटि है:
अनियंत्रित अपवाद:
System.NullReferenceException: ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट की आवृत्ति के लिए सेट नहीं है। कार्यक्रम में। मेन ()
हालांकि इस तरह के अपवाद से बचने / ठीक करने के लिए एक NullReferenceException और दृष्टिकोण का क्या कारण होता है, अन्य उत्तरों में संबोधित किया गया है, जो कई प्रोग्रामर अभी तक नहीं सीख पाए हैं कि विकास के दौरान ऐसे अपवादों को कैसे स्वतंत्र रूप से डिबग किया जाए ।
विजुअल स्टूडियो में यह आमतौर पर विज़ुअल स्टूडियो डीबगर के लिए आसान धन्यवाद है ।
पहले, सुनिश्चित करें कि सही त्रुटि पकड़ी जा रही है - देखें कि मैं VS2010 में 'System.NullReferenceException' पर टूटने की अनुमति कैसे दूं? नोट 1
तो फिर या तो प्रारंभ डिबगिंग (F5) के साथ या संलग्न [वी.एस. डीबगर] चल रही प्रक्रिया के लिए । मौके पर यह उपयोग करने के लिए उपयोगी हो सकता है Debugger.Break
, जो डिबगर को लॉन्च करने के लिए संकेत देगा।
अब, जब NullReferenceException को फेंक दिया जाता है (या अनहेल्ड किया जाता है) डीबगर बंद हो जाएगा (उस नियम को याद रखें? ऊपर लाइन पर?) जिस पर अपवाद हुआ। कभी-कभी त्रुटि को स्पॉट करना आसान होगा।
उदाहरण के लिए, निम्न पंक्ति में केवल कोड है कि कर सकते हैं अपवाद के कारण अगर है myString
मूल्यांकन करता अशक्त करने के लिए। यह वॉच विंडो को देखकर या तत्काल विंडो में चल रहे अभिव्यक्तियों को सत्यापित किया जा सकता है ।
var x = myString.Trim();
अधिक उन्नत मामलों में, जैसे कि निम्नलिखित, आपको उपरोक्त तकनीकों में से एक (वॉच या तत्काल विंडोज) का उपयोग करने की आवश्यकता होगी, यह निर्धारित करने के लिए कि क्या str1
अशक्त था या यदि अशक्त था, तो निरीक्षण करने के लिए str2
।
var x = str1.Trim() + str2.Trim();
एक बार जहां अपवाद को फेंक दिया गया है, वहां आमतौर पर यह पता लगाने के लिए कि तुच्छ मान कहाँ था, यह पता लगाने के लिए तुच्छ है कि यह गलत तरीके से पेश किया गया था -
अपवाद के कारण को समझने के लिए आवश्यक समय निकालें। अशक्त भावों का निरीक्षण करें। पिछली अभिव्यक्तियों का निरीक्षण करें जिसके परिणामस्वरूप ऐसे अशक्त भाव हो सकते हैं। ब्रेकपॉइंट्स जोड़ें और कार्यक्रम के माध्यम से उचित रूप में कदम रखें। डीबगर का उपयोग करें।
1 यदि थ्रो पर ब्रेक बहुत आक्रामक है और डीबगर .NET या 3-पार्टी लाइब्रेरी में एक एनपीई पर रुक जाता है, तो पकड़े गए अपवादों को सीमित करने के लिए यूजर-अनहेल्ड पर ब्रेक का उपयोग किया जा सकता है। इसके अतिरिक्त, VS2012 जस्ट माई कोड का परिचय देता है जिसे मैं सक्षम करने की सलाह देता हूं।
यदि आप जस्ट माई कोड सक्षम के साथ डिबगिंग कर रहे हैं, तो व्यवहार थोड़ा अलग है। जस्ट माई कोड सक्षम होने के साथ, डिबगर पहले-अवसर की सामान्य भाषा रनटाइम (CLR) अपवादों को अनदेखा करता है, जो मेरे कोड के बाहर फेंक दिए जाते हैं और मेरे कोड से नहीं गुजरते हैं
साइमन मॉरियर ने यह उदाहरण दिया :
object o = null;
DateTime d = (DateTime)o; // NullReferenceException
जहां एक unboxing रूपांतरण (डाली) से object
(या वर्गों में से एक से System.ValueType
या System.Enum
, या एक इंटरफ़ेस प्रकार से) के लिए एक मान प्रकार (के अलावा अन्य Nullable<>
) अपने आप में देता हैNullReferenceException
।
दूसरी दिशा में, एक बॉक्सिंग रूपांतरण से एक Nullable<>
जो है HasValue
के बराबर false
करने के लिए एक संदर्भ के प्रकार, एक दे सकते हैं null
संदर्भ जो फिर बाद में एक को जन्म दे सकता NullReferenceException
। क्लासिक उदाहरण है:
DateTime? d = null;
var s = d.ToString(); // OK, no exception (no boxing), returns ""
var t = d.GetType(); // Bang! d is boxed, NullReferenceException
कभी-कभी बॉक्सिंग दूसरे तरीके से होती है। इस गैर-जेनेरिक एक्सटेंशन विधि के साथ उदाहरण के लिए:
public static void MyExtension(this object x)
{
x.ToString();
}
निम्नलिखित कोड समस्याग्रस्त होगा:
DateTime? d = null;
d.MyExtension(); // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.
बॉक्सिंग के Nullable<>
उदाहरणों के दौरान रनटाइम का उपयोग करने वाले विशेष नियमों के कारण ये मामले उत्पन्न होते हैं ।
एक ऐसा मामला जोड़ना जब इकाई ढांचे में प्रयुक्त इकाई का वर्ग नाम वेब प्रपत्र कोड-पीछे फ़ाइल के वर्ग नाम के समान हो।
मान लीजिए कि आपके पास एक वेब फ़ॉर्म Contact.aspx है जिसका कोडबेहाइंड संपर्क है और आपके पास एक इकाई का नाम संपर्क है।
जब आप संदर्भ कहते हैं तब निम्नलिखित कोड एक NullReferenceException फेंक देगा। ShaveChanges ()
Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line
संपूर्णता के लिए DataContext वर्ग
public class DataContext : DbContext
{
public DbSet<Contact> Contacts {get; set;}
}
और संपर्क इकाई वर्ग। कभी-कभी इकाई वर्ग आंशिक वर्ग होते हैं ताकि आप उन्हें अन्य फ़ाइलों में भी विस्तारित कर सकें।
public partial class Contact
{
public string Name {get; set;}
}
त्रुटि तब होती है जब दोनों निकाय और कोडबिहिन वर्ग समान नामस्थान में होते हैं। इसे ठीक करने के लिए, संपर्क वर्ग के लिए संस्था वर्ग या Codebehind वर्ग का नाम बदलें ।aspx।
कारण मैं अभी भी कारण के बारे में निश्चित नहीं हूं। लेकिन जब भी कोई इकाई वर्ग System.Web.UI का विस्तार करेगा। इस त्रुटि के कारण होता है।
चर्चा के लिए DbContext.saveChanges () में NullReferenceException पर एक नज़र डालें
एक अन्य सामान्य मामला जहां किसी को यह अपवाद प्राप्त हो सकता है, उसमें यूनिट परीक्षण के दौरान मॉकिंग कक्षाएं शामिल हैं। भले ही मॉकिंग फ्रेमवर्क का उपयोग किया जा रहा हो, आपको यह सुनिश्चित करना होगा कि वर्ग पदानुक्रम के सभी उपयुक्त स्तर ठीक से मॉक किए गए हों। विशेष रूप से, HttpContext
परीक्षण के तहत कोड द्वारा संदर्भित किए जाने वाले सभी गुणों का मजाक उड़ाया जाना चाहिए।
कुछ हद तक उदाहरण के लिए कस्टम ऑथोराइज़ेशन एट्रिब्यूट का परीक्षण करते समय " NullReferenceException " को देखें ।
इसका उत्तर देने के लिए मेरे पास एक अलग दृष्टिकोण है। इस तरह के जवाब "मैं इससे बचने के लिए और क्या कर सकता हूं? "
विभिन्न परतों में काम करते समय , उदाहरण के लिए एक एमवीसी एप्लिकेशन में, एक नियंत्रक को व्यावसायिक कार्यों को कॉल करने के लिए सेवाओं की आवश्यकता होती है। ऐसे परिदृश्यों में NullReferenceException से बचने के लिए सेवाओं को प्रारंभ करने के लिए निर्भरता इंजेक्शन कंटेनर का उपयोग किया जा सकता है । इसका मतलब है कि आपको अशक्त के लिए जाँच करने के बारे में चिंता करने की आवश्यकता नहीं है और बस नियंत्रक से सेवाओं को कॉल करें क्योंकि वे हमेशा उपलब्ध हैं (और आरंभिक) या तो एक सिंगलटन या एक प्रोटोटाइप के रूप में।
public class MyController
{
private ServiceA serviceA;
private ServiceB serviceB;
public MyController(ServiceA serviceA, ServiceB serviceB)
{
this.serviceA = serviceA;
this.serviceB = serviceB;
}
public void MyMethod()
{
// We don't need to check null because the dependency injection container
// injects it, provided you took care of bootstrapping it.
var someObject = serviceA.DoThis();
}
}
"मुझे इसके बारे में क्या करना चाहिए" की बात पर , कई जवाब हो सकते हैं।
विकसित करते समय ऐसी त्रुटि स्थितियों को रोकने का एक अधिक "औपचारिक" तरीका आपके कोड में अनुबंध द्वारा डिजाइन लागू कर रहा है । इसका मतलब है आप सेट वर्ग की जरूरत अपरिवर्तनशीलताओं , और / या यहां तक कि समारोह / विधि पूर्व शर्त और postconditions आपके सिस्टम पर है, जबकि विकासशील।
संक्षेप में, वर्ग के आक्रमणकारी यह सुनिश्चित करते हैं कि आपकी कक्षा में कुछ अड़चनें होंगी जो सामान्य उपयोग में उल्लंघन नहीं करेंगी (और इसलिए, वर्ग असंगत स्थिति में नहीं मिलेगा)। Preconditions का मतलब है कि किसी फ़ंक्शन / मेथड के इनपुट के रूप में दिए गए डेटा को कुछ बाधाओं का पालन करना चाहिए और उनका उल्लंघन कभी नहीं करना चाहिए, और पोस्टकंडिशन का अर्थ है कि फ़ंक्शन / मेथोड आउटपुट को कभी भी उल्लंघन किए बिना सेट की कमी का पालन करना चाहिए। बग-मुक्त कार्यक्रम के निष्पादन के दौरान अनुबंध की शर्तों का कभी भी उल्लंघन नहीं किया जाना चाहिए , इसलिए अनुबंध द्वारा डिजाइन को डिबग मोड में अभ्यास में जांचा जाता है, जबकि रिलीज में अक्षम होने के दौरान , विकसित सिस्टम प्रदर्शन को अधिकतम करने के लिए।
इस तरह, आप उन NullReferenceException
मामलों से बच सकते हैं जो निर्धारित बाधाओं के उल्लंघन के परिणाम हैं। उदाहरण के लिए, यदि आप X
किसी क्लास में ऑब्जेक्ट प्रॉपर्टी का उपयोग करते हैं और बाद में इसके किसी एक तरीके को लागू करने की कोशिश करते हैं और X
इसका एक शून्य मान है, तो यह इस प्रकार होगा NullReferenceException
:
public X { get; set; }
public void InvokeX()
{
X.DoSomething(); // if X value is null, you will get a NullReferenceException
}
लेकिन अगर आपने "प्रॉपर्टी एक्स को कभी शून्य मान नहीं होना चाहिए" विधि पूर्व शर्त के रूप में, तो आप पहले वर्णित परिदृश्य को रोक सकते हैं:
//Using code contracts:
[ContractInvariantMethod]
protected void ObjectInvariant ()
{
Contract.Invariant ( X != null );
//...
}
इस कारण से, .NET कॉन्ट्रैक्ट्स प्रोजेक्ट .NET अनुप्रयोगों के लिए मौजूद है।
वैकल्पिक रूप से, अनुबंध द्वारा डिजाइन अभिकथन का उपयोग करके लागू किया जा सकता है ।
अद्यतन: यह उल्लेखनीय है कि यह शब्द बर्ट्रेंड मेयर ने एफिल प्रोग्रामिंग भाषा के अपने डिजाइन के संबंध में बनाया था ।
ए NullReferenceException
तब फेंका जाता है जब हम एक अशक्त वस्तु के गुणों का उपयोग करने की कोशिश कर रहे हैं या जब एक स्ट्रिंग मान रिक्त हो जाता है और हम स्ट्रिंग विधियों तक पहुंचने का प्रयास कर रहे हैं।
उदाहरण के लिए:
जब एक खाली स्ट्रिंग की एक स्ट्रिंग विधि एक्सेस की जाती है:
string str = string.Empty;
str.ToLower(); // throw null reference exception
जब किसी अशक्त वस्तु की संपत्ति एक्सेस की जाती है:
Public Class Person {
public string Name { get; set; }
}
Person objPerson;
objPerson.Name /// throw Null refernce Exception
String.Empty.ToLower()
एक अशक्त संदर्भ अपवाद नहीं फेंकेंगे। यह एक वास्तविक स्ट्रिंग का प्रतिनिधित्व करता है, भले ही एक खाली (यानी ""
)। चूंकि इस ToLower()
पर कॉल करने के लिए एक ऑब्जेक्ट है , इसलिए यह एक शून्य संदर्भ अपवाद को फेंकने के लिए कोई मतलब नहीं होगा।
TL; DR: केHtml.Partial
बजाय का उपयोग करने का प्रयास करेंRenderpage
Object reference not set to an instance of an object
जब मैं इसे एक मॉडल भेजकर एक दृश्य के भीतर एक दृश्य को प्रस्तुत करने की कोशिश कर रहा था , तो इस तरह से:
@{
MyEntity M = new MyEntity();
}
@RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null
डिबगिंग ने दिखाया कि मॉडल MyOtherView के अंदर अशक्त था। जब तक मैंने इसे नहीं बदला:
@{
MyEntity M = new MyEntity();
}
@Html.Partial("_MyOtherView.cshtml", M);
और इसने काम किया।
इसके अलावा, जिस कारण से मुझे Html.Partial
शुरुआत नहीं करनी पड़ी, क्योंकि विजुअल स्टूडियो कभी - कभी एरर दिखने वाली स्क्वीजीली लाइनों को फेंक देता है, Html.Partial
अगर यह एक अलग तरीके से निर्मित foreach
लूप के अंदर है , भले ही यह वास्तव में एक त्रुटि न हो:
@inherits System.Web.Mvc.WebViewPage
@{
ViewBag.Title = "Entity Index";
List<MyEntity> MyEntities = new List<MyEntity>();
MyEntities.Add(new MyEntity());
MyEntities.Add(new MyEntity());
MyEntities.Add(new MyEntity());
}
<div>
@{
foreach(var M in MyEntities)
{
// Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
@Html.Partial("MyOtherView.cshtml");
}
}
</div>
लेकिन मैं इस "त्रुटि" के साथ कोई समस्या नहीं के साथ आवेदन को चलाने में सक्षम था। मैं foreach
इस तरह दिखने के लिए लूप की संरचना को बदलकर त्रुटि से छुटकारा पाने में सक्षम था :
@foreach(var M in MyEntities){
...
}
हालाँकि मुझे ऐसा लग रहा है क्योंकि विजुअल स्टूडियो एम्परसेंड और ब्रैकेट का गलत इस्तेमाल कर रहा था।
Html.Partial
, नहीं@Html.Partial
Null
), इसलिए मुझे पता था कि त्रुटि यह थी कि मैं मॉडल को अंदर कैसे भेज रहा था।
आप इसके बारे में क्या कर सकते हैं?
यहाँ बहुत सारे अच्छे उत्तर हैं जो बताते हैं कि एक अशक्त संदर्भ क्या है और इसे कैसे डीबग करना है। लेकिन इस मुद्दे को रोकने के लिए या कम से कम इसे पकड़ने में आसान बनाने के तरीके पर बहुत कम है।
तर्कों की जाँच करें
उदाहरण के लिए, विधियाँ अलग-अलग तर्कों की जाँच कर सकती हैं कि क्या वे अशक्त हैं और उन्हें फेंक देते हैं ArgumentNullException
, एक अपवाद स्पष्ट रूप से इस सटीक उद्देश्य के लिए बनाया गया है।
ArgumentNullException
यहां तक कि कंस्ट्रक्टर भी पैरामीटर का नाम लेता है और तर्क के रूप में एक संदेश देता है ताकि आप डेवलपर को बता सकें कि समस्या क्या है।
public void DoSomething(MyObject obj) {
if(obj == null)
{
throw new ArgumentNullException("obj", "Need a reference to obj.");
}
}
उपकरण का उपयोग करें
कई पुस्तकालय भी हैं जो मदद कर सकते हैं। उदाहरण के लिए "रिचार्पर" आपको कोड लिखते समय चेतावनी दे सकता है, खासकर यदि आप उनकी विशेषता का उपयोग करते हैं: NotNullAttribute
वहाँ "Microsoft कोड कॉन्ट्रैक्ट्स" होता है जहाँ आप सिंटैक्स का उपयोग करते हैं, Contract.Requires(obj != null)
जो आपको रनटाइम देता है और जाँच करता है: कोड कॉन्ट्रैक्ट्स का परिचय ।
वहाँ भी है "PostSharp" जो आपको इस तरह की विशेषताओं का उपयोग करने की अनुमति देगा:
public void DoSometing([NotNull] obj)
ऐसा करने से और आपकी बिल्ड प्रक्रिया का PostSharp भाग बनाने के obj
लिए रनटाइम पर नल की जाँच की जाएगी। देखें: PostSharp अशक्त जाँच
सादा कोड समाधान
या आप हमेशा पुराने पुराने कोड का उपयोग करके अपने स्वयं के दृष्टिकोण को कोड कर सकते हैं। उदाहरण के लिए यहां एक संरचना है जिसे आप अशक्त संदर्भों को पकड़ने के लिए उपयोग कर सकते हैं। इसे उसी अवधारणा के बाद बनाया गया है Nullable<T>
:
[System.Diagnostics.DebuggerNonUserCode]
public struct NotNull<T> where T: class
{
private T _value;
public T Value
{
get
{
if (_value == null)
{
throw new Exception("null value not allowed");
}
return _value;
}
set
{
if (value == null)
{
throw new Exception("null value not allowed.");
}
_value = value;
}
}
public static implicit operator T(NotNull<T> notNullValue)
{
return notNullValue.Value;
}
public static implicit operator NotNull<T>(T value)
{
return new NotNull<T> { Value = value };
}
}
आप बिल्कुल उसी तरह का उपयोग करेंगे जैसे आप उपयोग करेंगे Nullable<T>
, बिल्कुल विपरीत को पूरा करने के लक्ष्य के अलावा - अनुमति नहीं देने के लिए null
। यहाँ कुछ उदाहरण हैं:
NotNull<Person> person = null; // throws exception
NotNull<Person> person = new Person(); // OK
NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null
NotNull<T>
से अनुमानित रूप से है और T
इसलिए आप इसका उपयोग कर सकते हैं बस के बारे में कहीं भी आप की जरूरत है। उदाहरण के लिए, आप किसी Person
ऑब्जेक्ट को एक विधि में पास कर सकते हैं जो एक NotNull<Person>
:
Person person = new Person { Name = "John" };
WriteName(person);
public static void WriteName(NotNull<Person> person)
{
Console.WriteLine(person.Value.Name);
}
जैसा कि आप अशक्त के साथ ऊपर देख सकते हैं कि आप Value
संपत्ति के माध्यम से अंतर्निहित मूल्य तक पहुंचेंगे । वैकल्पिक रूप से, आप एक स्पष्ट या निहित कलाकारों का उपयोग कर सकते हैं, आप नीचे दिए गए रिटर्न मान के साथ एक उदाहरण देख सकते हैं:
Person person = GetPerson();
public static NotNull<Person> GetPerson()
{
return new Person { Name = "John" };
}
या आप इसका उपयोग तब भी कर सकते हैं जब विधि सिर्फ एक कास्ट करके T
(इस मामले में Person
) वापस आती है । उदाहरण के लिए, निम्न कोड ऊपर दिए गए कोड की तरह होगा:
Person person = (NotNull<Person>)GetPerson();
public static Person GetPerson()
{
return new Person { Name = "John" };
}
एक्सटेंशन के साथ मिलाएं
NotNull<T>
एक विस्तार विधि के साथ गठबंधन करें और आप और भी अधिक स्थितियों को कवर कर सकते हैं। विस्तार विधि क्या दिख सकती है, इसका एक उदाहरण इस प्रकार है:
[System.Diagnostics.DebuggerNonUserCode]
public static class NotNullExtension
{
public static T NotNull<T>(this T @this) where T: class
{
if (@this == null)
{
throw new Exception("null value not allowed");
}
return @this;
}
}
और इसका एक उदाहरण है कि इसका उपयोग कैसे किया जा सकता है:
var person = GetPerson().NotNull();
GitHub
आपके संदर्भ के लिए मैंने ऊपर GitHub पर कोड उपलब्ध कराया, आप इसे यहाँ पा सकते हैं:
https://github.com/luisperezphd/NotNull
संबंधित भाषा फ़ीचर
सी # 6.0 ने "नल-सशर्त ऑपरेटर" को पेश किया जो इसे थोड़ा मदद करता है। इस सुविधा के साथ, आप नेस्टेड ऑब्जेक्ट्स को संदर्भित कर सकते हैं और यदि उनमें से कोई एक null
पूरी अभिव्यक्ति रिटर्न है null
।
यह कुछ मामलों में आपको किए जाने वाले शून्य चेक की संख्या को कम कर देता है। वाक्य-विन्यास को प्रत्येक बिंदु से पहले प्रश्न चिह्न लगाना है। उदाहरण के लिए निम्न कोड लें:
var address = country?.State?.County?.City;
कल्पना कीजिए कि country
एक प्रकार की एक वस्तु Country
है जिसमें एक संपत्ति है जिसे बुलाया जाता है State
और इसी तरह। तो country
, State
, County
, या City
है null
तो address will be
अशक्त . Therefore you only have to check whether
पताis
null`।
यह एक बड़ी विशेषता है, लेकिन यह आपको कम जानकारी देता है। यह स्पष्ट नहीं करता है कि 4 में से कौन सा शून्य है।
बिल्ट-इन Nullable की तरह?
C # के लिए एक अच्छा शॉर्टहैंड है Nullable<T>
, आप इस प्रकार के बाद प्रश्न चिह्न लगाकर कुछ अशक्त कर सकते हैं int?
।
यह अच्छा होगा यदि C # में NotNull<T>
ऊपर की संरचना जैसी कोई चीज़ होती और उसके पास एक समान शॉर्टहैंड होता, शायद विस्मयादिबोधक बिंदु (!) ताकि आप कुछ ऐसा लिख सकें:public void WriteName(Person! person)
:।
दिलचस्प बात यह है कि इस पृष्ठ पर कोई भी उत्तर दो किनारे के मामलों का उल्लेख नहीं करता है, आशा है कि अगर मैं उन्हें जोड़ दूं तो कोई भी बुरा नहीं मानता:
.NET में जेनेरिक शब्दकोश थ्रेड-सुरक्षित नहीं हैं और वे कभी - कभीNullReference
या (अधिक लगातार) ए भी फेंक सकते हैंKeyNotFoundException
जब आप दो समवर्ती धागों से एक कुंजी को एक्सेस करने का प्रयास करते हैं तो । इस मामले में अपवाद काफी भ्रामक है।
यदि कोड NullReferenceException
द्वारा फेंक दिया गया है unsafe
, तो आप अपने पॉइंटर चर को देख सकते हैं, और उन्हें जांच सकते हैंIntPtr.Zero
या कुछ के । जो एक ही बात है ("शून्य सूचक अपवाद"), लेकिन असुरक्षित कोड में, चर अक्सर मूल्य-प्रकार / सरणियों, आदि के लिए डाली जाती हैं, और आप दीवार के खिलाफ अपना सिर धमाका करते हैं, यह सोचकर कि मूल्य-प्रकार इसे कैसे फेंक सकते हैं अपवाद।
(असुरक्षित कोड का उपयोग न करने का एक अन्य कारण जब तक आपको इसकी आवश्यकता नहीं है, वैसे)
null
किस तरह से अलग है ?
Null-सशर्त ऑपरेटर्स को c # 6 का उपयोग करके आप एक साफ तरीके से NullReferenceException को ठीक कर सकते हैं और अशक्त जांच को संभालने के लिए कम कोड लिख सकते हैं।
इसका उपयोग एक सदस्य पहुंच (?) या इंडेक्स (? [) ऑपरेशन करने से पहले अशक्त के लिए परीक्षण करने के लिए किया जाता है।
उदाहरण
var name = p?.Spouse?.FirstName;
के बराबर है:
if (p != null)
{
if (p.Spouse != null)
{
name = p.Spouse.FirstName;
}
}
नतीजा यह है कि नाम शून्य होगा जब p शून्य है या जब p.Spouse शून्य है।
अन्यथा, चर नाम को p.Spouse.FirstName का मान असाइन किया जाएगा।
अधिक जानकारी के लिए: अशक्त-संचालक
त्रुटि लाइन "ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट के उदाहरण के लिए सेट नहीं है।" बताता है कि आपने ऑब्जेक्ट ऑब्जेक्ट को इंस्टेंस ऑब्जेक्ट को नहीं सौंपा है और फिर भी आप उस ऑब्जेक्ट की उचितियों / विधियों तक पहुंच बना रहे हैं।
उदाहरण के लिए: मान लें कि आपके पास myClass नामक एक वर्ग है और इसमें एक संपत्ति Prop1 है।
public Class myClass
{
public int prop1 {get;set;}
}
अब आप इस प्रॉप 1 को नीचे की तरह किसी अन्य वर्ग में पहुँचा रहे हैं:
public class Demo
{
public void testMethod()
{
myClass ref = null;
ref.prop1 = 1; //This line throws error
}
}
उपरोक्त लाइन त्रुटि को फेंकती है क्योंकि वर्ग myClass का संदर्भ घोषित किया गया है, लेकिन तात्कालिक या वस्तु का एक उदाहरण उस वर्ग के संदर्भ के लिए निर्दिष्ट नहीं किया गया है।
इसे ठीक करने के लिए आपको तुरंत (उस वर्ग के संदर्भ में ऑब्जेक्ट असाइन करना होगा)।
public class Demo
{
public void testMethod()
{
myClass ref = null;
ref = new myClass();
ref.prop1 = 1;
}
}
NullReferenceException या ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट के इंस्टेंस पर सेट नहीं होता है, जब आप जिस क्लास का उपयोग करने का प्रयास कर रहे हैं, उस ऑब्जेक्ट का इंस्टेंटिएटेड नहीं है। उदाहरण के लिए:
मान लें कि आपके पास छात्र नाम का एक वर्ग है।
public class Student
{
private string FirstName;
private string LastName;
public string GetFullName()
{
return FirstName + LastName;
}
}
अब, एक और कक्षा पर विचार करें जहाँ आप छात्र का पूरा नाम पुनः प्राप्त करने का प्रयास कर रहे हैं।
public class StudentInfo
{
public string GetStudentName()
{
Student s;
string fullname = s.GetFullName();
return fullname;
}
}
जैसा कि ऊपर दिए गए कोड में देखा गया है, छात्र का कथन - केवल छात्र का चर घोषित करता है, ध्यान दें कि छात्र वर्ग इस बिंदु पर त्वरित नहीं है। इसलिए, जब कथन s.GetFullName () निष्पादित हो जाता है, तो यह NullReferenceException को फेंक देगा।
ठीक है, सरल शब्दों में:
आप उस ऑब्जेक्ट तक पहुँचने का प्रयास कर रहे हैं जो अभी बना नहीं है या वर्तमान में मेमोरी में नहीं है।
तो इससे कैसे निपटा जाए:
डीबग करें और डीबगर को विराम दें ... यह सीधे आपको उस चर पर ले जाएगा जो टूट गया है ... अब आपका कार्य बस इसे ठीक करना है .. नए कीवर्ड का उपयोग उचित स्थान पर करना।
यदि यह कुछ डेटाबेस कमांड्स पर होता है क्योंकि ऑब्जेक्ट मौजूद नहीं है, तो आपको बस इतना करना है कि एक अशक्त जांच करें और इसे संभाल लें:
if (i == null) {
// Handle this
}
सबसे कठिन .. यदि GC ने पहले ही ऑब्जेक्ट एकत्र कर लिया है ... यह आमतौर पर तब होता है जब आप स्ट्रिंग्स का उपयोग करके ऑब्जेक्ट खोजने का प्रयास कर रहे हैं ... अर्थात, इसे ऑब्जेक्ट के नाम से ढूंढना है तो ऐसा हो सकता है कि GC पहले से ही हो सकता है इसे साफ कर दिया ... यह खोजने के लिए कठिन है और काफी समस्या बन जाएगा ... इससे निपटने का एक बेहतर तरीका यह है कि विकास प्रक्रिया के दौरान जहां भी आवश्यक हो, अशक्त जांच करें। इससे आपका काफी समय बचेगा।
नाम से खोजने से मेरा मतलब है कि कुछ ढांचे आपको स्ट्रिंग का उपयोग करके FIndObjects की अनुमति देते हैं और कोड इस तरह दिख सकता है: FindObject ("ObjectName");
मूल रूप से NullReferenceExeption को ठीक करने का सबसे आसान तरीका दो तरीके हैं। यदि आपके पास उदाहरण के लिए एक GameObject जुड़ा हुआ है और लिपि में rb (rigidbody) नाम का एक चर है, तो यह चर आपके खेल को शुरू करते समय अशक्त हो जाएगा।
यही कारण है कि आपको NullReferenceExeption मिलता है क्योंकि कंप्यूटर में उस चर में संग्रहीत डेटा नहीं होता है।
मैं एक उदाहरण के रूप में एक RigidBody चर का उपयोग करूँगा।
हम वास्तव में आसानी से वास्तव में कुछ तरीकों से डेटा जोड़ सकते हैं:
rb = GetComponent<Rigidbody>();
Start()
या Awake()
फ़ंक्शंस के तहत सबसे अच्छा काम करती है। rb = AddComponent<RigidBody>();
आगे के नोट्स: यदि आप एकता को अपनी वस्तु में जोड़ना चाहते हैं और आप एक को जोड़ना भूल गए हैं, तो आप [RequireComponent(typeof(RigidBody))]
अपनी कक्षा की घोषणा (आपके सभी विवरणों के नीचे का स्थान) से ऊपर टाइप कर सकते हैं ।
आनंद लें और खेल बनाने का मज़ा लें!
यदि हम सामान्य परिदृश्यों पर विचार करते हैं, जहां इस अपवाद को फेंक दिया जा सकता है, तो शीर्ष पर ऑब्जेक्ट को एक्सेस करने वाले गुणों तक पहुंचना।
उदाहरण के लिए:
string postalcode=Customer.Address.PostalCode;
//if customer or address is null , this will through exeption
यहाँ, यदि पता शून्य है, तो आपको NullReferenceException मिल जाएगी।
इसलिए, एक अभ्यास के रूप में हमें हमेशा ऐसी वस्तुओं में संपत्तियों तक पहुंचने से पहले (विशेष रूप से सामान्य में) अशक्त जांच का उपयोग करना चाहिए
string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception
यह मूल रूप से अशक्त संदर्भ अपवाद है । जैसा कि Microsoft बताता है-
जब आप किसी ऐसे प्रकार के सदस्य तक पहुँचने का प्रयास करते हैं, जिसका मान शून्य है, तो NullReferenceException अपवाद को फेंक दिया जाता है।
इसका मतलब है कि यदि कोई भी सदस्य जो कोई मूल्य नहीं रखता है और हम उस सदस्य को कुछ कार्य करने के लिए बना रहे हैं, तो सिस्टम निस्संदेह एक संदेश को टॉस करेगा और कहेगा-
"अरे रुको, उस सदस्य के पास कोई मूल्य नहीं है इसलिए यह उस कार्य को नहीं कर सकता है जिसे आप इसे सौंप रहे हैं।"
अपवाद खुद कहता है कि कुछ संदर्भित किया जा रहा है, लेकिन जिसका मूल्य निर्धारित नहीं किया जा रहा है। तो यह दर्शाता है कि यह केवल संदर्भ प्रकारों का उपयोग करते समय होता है क्योंकि मान प्रकार गैर-अशक्त होते हैं।
यदि हम मान प्रकार के सदस्यों का उपयोग कर रहे हैं तो NullReferenceException नहीं होगी।
class Program
{
static void Main(string[] args)
{
string str = null;
Console.WriteLine(str.Length);
Console.ReadLine();
}
}
उपरोक्त कोड सरल स्ट्रिंग दिखाता है जिसे एक शून्य मान के साथ सौंपा गया है ।
अब, जब मैं स्ट्रिंग की लंबाई प्रिंट करने का प्रयास str , मैं मिलता है प्रकार के 'System.NullReferenceException' एक अनियंत्रित अपवाद घटित संदेश क्योंकि सदस्य str अशक्त की ओर इशारा करते है और वहाँ बातिल के किसी भी लम्बाई नहीं हो सकता।
' NullReferenceException ' तब भी होती है जब हम किसी संदर्भ प्रकार को तुरंत लिखना भूल जाते हैं।
मान लीजिए कि मेरे पास इसमें एक वर्ग और सदस्य विधि है। मैंने अपनी कक्षा को तत्काल नहीं किया है बल्कि केवल अपनी कक्षा का नाम रखा है। अब अगर मैं विधि का उपयोग करने की कोशिश करता हूं, तो संकलक एक त्रुटि फेंक देगा या एक चेतावनी जारी करेगा (संकलक के आधार पर)।
class Program
{
static void Main(string[] args)
{
MyClass1 obj;
obj.foo(); //Use of unassigned local variable 'obj'
}
}
public class MyClass1
{
internal void foo()
{
Console.WriteLine("hello from foo");
}
}
उपरोक्त कोड के लिए कंपाइलर एक त्रुटि उठाता है कि वेरिएबल ओबीज अनसाइनड है जो दर्शाता है कि हमारे वेरिएबल में शून्य मान या कुछ भी नहीं है। उपरोक्त कोड के लिए कंपाइलर एक त्रुटि उठाता है कि वेरिएबल ओबीज अनसाइनड है जो दर्शाता है कि हमारे वेरिएबल में शून्य मान या कुछ भी नहीं है।
NullReferenceException ऑब्जेक्ट के मान की जाँच नहीं करने के लिए हमारी गलती के कारण उत्पन्न होती है। हम अक्सर कोड विकास में अनियंत्रित वस्तु मूल्यों को छोड़ देते हैं।
यह तब भी उठता है जब हम अपनी वस्तुओं को पलटना भूल जाते हैं। तरीकों, गुणों, संग्रह आदि का उपयोग करना जो अशक्त मूल्यों को वापस कर सकते हैं या सेट कर सकते हैं, इस अपवाद का कारण भी हो सकता है।
इस प्रसिद्ध अपवाद से बचने के विभिन्न तरीके और तरीके हैं:
स्पष्ट जाँच: हमें वस्तुओं, गुणों, विधियों, सरणियों और संग्रह की जाँच करने की परंपरा का पालन करना चाहिए, चाहे वे शून्य हों। यह बस सशर्त बयानों का उपयोग करके लागू किया जा सकता है, जैसे कि-इफ-इफ-अगर आदि।
अपवाद हैंडलिंग: इस अपवाद को प्रबंधित करने के महत्वपूर्ण तरीकों में से एक। सरल कोशिश-कैच-अंततः ब्लॉकों का उपयोग करके हम इस अपवाद को नियंत्रित कर सकते हैं और इसका लॉग भी बनाए रख सकते हैं। यह तब बहुत उपयोगी हो सकता है जब आपका एप्लिकेशन प्रोडक्शन स्टेज पर हो।
अशक्त संचालक: वस्तुओं, चरों, संपत्तियों और क्षेत्रों में मूल्यों को स्थापित करते समय अशक्त संचालक संचालक और अशक्त सशर्त संचालकों को भी काम में लिया जा सकता है।
डिबगर: डेवलपर्स के लिए, हमारे पास डीबगिंग का बड़ा हथियार है। अगर हम विकास के चेहरे के दौरान NullReferenceException का सामना करते हैं तो हम अपवाद के स्रोत तक पहुंचने के लिए डीबगर का उपयोग कर सकते हैं।
इन-बिल्ट विधि: सिस्टम विधियाँ जैसे GetValueOrDefault (), IsNullOrWhiteSpace () और IsNullorEmpty () नल के लिए जाँच करता है और यदि कोई शून्य मान है तो डिफ़ॉल्ट मान असाइन करें।
यहां पहले से ही कई अच्छे जवाब हैं। आप मेरे ब्लॉग पर उदाहरणों के साथ अधिक विस्तृत विवरण भी देख सकते हैं ।
आशा है कि यह भी मदद करता है!
अगर किसी को बिल्ड को सेव या कंपेयर करने के दौरान यह मैसेज मिल रहा है, तो बस सभी फाइलों को बंद कर दें और फिर किसी फाइल को कंपाइल करके सेव करें।
मेरे लिए इसका कारण यह था कि मैंने फ़ाइल का नाम बदल दिया था और पुरानी फ़ाइल अभी भी खुली हुई थी।