මට යම් කේතයක් ඇති අතර එය ක්රියාත්මක වන විට එය NullReferenceExceptionමෙසේ විසි කරයි .
වස්තු සමුද්දේෂය වස්තුවක උදාහරණයකට පිහිටුවා නැත.
මෙයින් අදහස් කරන්නේ කුමක්ද, මෙම දෝෂය නිවැරදි කිරීමට මට කුමක් කළ හැකිද?
මට යම් කේතයක් ඇති අතර එය ක්රියාත්මක වන විට එය NullReferenceExceptionමෙසේ විසි කරයි .
වස්තු සමුද්දේෂය වස්තුවක උදාහරණයකට පිහිටුවා නැත.
මෙයින් අදහස් කරන්නේ කුමක්ද, මෙම දෝෂය නිවැරදි කිරීමට මට කුමක් කළ හැකිද?
Answers:
ඔබ උත්සාහ කරන්නේ null(හෝ NothingVB.NET හි) යමක් භාවිතා කිරීමට ය . මෙයින් අදහස් කරන්නේ ඔබ එය සකසා ඇති බවයි null, නැතහොත් ඔබ එය කිසිසේත් කිසිසේත් සකසා නැත.
වෙනත් ඕනෑම දෙයක් මෙන්, nullවටේට ගමන් කරයි. එය නම් null දී ක්රමය "A", එය, එම කමෙව්දය විය හැකි 'බී' සම්මත null කිරීමට ක්රමයක් "A".
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.
A හි ප්රභවය ඔබ සොයා ගන්නේ කෙසේද NullReferenceException? මීට අමතරව විෂුවල් ස්ටුඩියෝ දී දෝෂහරණ පොදු නීති අදාළ වන්නේ නම්, එය සිදුවන ස්ථානයේ දී හරියටම දමනු ලැබේ වන ව්යතිරේකයක් ම දෙස බලා, සිට: ස්ථානය මූලෝපායාත්මක breakpoints හා ඔබගේ විචල්ය පරීක්ෂා විවර නම්, ඔවුන්ෙග් නම් පුරා මූසිකය ඩොලරයක විසින් එක්කෝ, ( ඉක්මන්) කවුළුව නරඹන්න හෝ ස්ථාන සහ ඔටෝස් වැනි විවිධ නිදොස් කිරීමේ පැනල් භාවිතා කරන්න.
ඔබට සඳහන කොතැනදැයි සොයා ගැනීමට අවශ්ය නම්, එහි නම දකුණු-ක්ලික් කර "සියලු යොමු සොයන්න" තෝරන්න. එවිට ඔබට සොයාගත් සෑම ස්ථානයකම බ්රේක්පොයින්ට් එකක් තැබිය හැකි අතර, නිදොස් කර ඇති ඔබේ වැඩසටහන ක්රියාත්මක කරන්න. එවැනි කඩාවැටීමක් මත නිදොස්කරණය බිඳෙන සෑම අවස්ථාවකම, ඔබ යොමු කිරීම ශුන්ය නොවන බව තීරණය කළ යුතුද, විචල්යය පරීක්ෂා කර, ඔබ එය අපේක්ෂා කරන අවස්ථාවකට එය යොමු කරනවාද යන්න තහවුරු කර ගත යුතුය.
ක්රමලේඛ ප්රවාහය මේ ආකාරයෙන් අනුගමනය කිරීමෙන්, උදාහරණය අහෝසි නොවිය යුතු ස්ථානය සහ එය නිසි ලෙස සකසා නොතිබීමට හේතුව සොයාගත හැකිය.
ව්යතිරේකය විසි කළ හැකි පොදු අවස්ථා කිහිපයක්:
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.
පොදු පංතිය Form1 {පුද්ගලික පාරිභෝගික පාරිභෝගිකයා;
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 -->
WPFInitializeComponentදෘශ්ය ගසෙහි දිස්වන අනුපිළිවෙලට ඇමතුම අතරතුර පාලනයන් නිර්මාණය වේ. NullReferenceExceptionසිදුවීම් හසුරුවන්නන් යනාදිය සමඟ කලින් සාදන ලද පාලනයන් සම්බන්ධයෙන් A මතු කරනු ඇත 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මෙහි විසඳනු ඇත.
asvar myThing = someObject as Thing;
මෙය විසි නොකරන InvalidCastExceptionනමුත් nullවාත්තු කිරීම අසමත් වූ විට (සහ someObjectඑය ශුන්ය වූ විට) නැවත ලබා දෙයි. එබැවින් ඒ ගැන සැලකිලිමත් වන්න.
FirstOrDefault()සහSingleOrDefault()කිසිවක් නොමැති විට සරල අනුවාදයන් First()සහ Single()විසි කිරීම් ව්යතිරේක. "OrDefault" අනුවාදයන් එම අවස්ථාවේ දී අහෝසි වේ. එබැවින් ඒ ගැන සැලකිලිමත් වන්න.
foreachඔබ ශුන්ය එකතු කිරීම නැවත කිරීමට උත්සාහ කරන විට විසි කරයි. nullඑකතු කිරීම් ආපසු ලබා දෙන ක්රම වලින් බලාපොරොත්තු නොවූ ප්රති result ලයක් නිසා සාමාන්යයෙන් සිදු වේ.
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()සඳහා භාවිතා කරන්න .nullablenullDateTime? 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ගොනුවේ ඇති මූලද්රව්යය භාවිතා කරමින් ව්යාපෘතියක් සඳහා ශුන්ය විවරණ සන්දර්භය සහ අවලංගු කළ හැකි අනතුරු ඇඟවීමේ සන්දර්භය සැකසිය හැකිය . මෙම මූලද්රව්යය සම්පාදකයා විසින් වර්ග වල ශුන්යතාවය අර්ථ නිරූපණය කරන්නේ කෙසේද සහ කුමන අනතුරු ඇඟවීම් ජනනය කරයිද යන්න වින්යාස කරයි. වලංගු සැකසුම්:
ශුන්ය අගය වර්ග වලට සමාන වාක්ය ඛණ්ඩයක් භාවිතා කරමින් ශුන්ය යොමු වර්ගයක් සටහන් කර ඇත: a ?විචල්යයේ වර්ගයට එකතු වේ.
C#"iterator block" සඳහා සහය දක්වයි (වෙනත් ජනප්රිය භාෂාවලින් "ජනක යන්ත්ර" ලෙස හැඳින්වේ). විලම්බිත ක්රියාත්මක කිරීම හේතුවෙන් ශුන්ය විරූපණ ව්යතිරේකයන් ඉටරේටර් බ්ලොක් වල නිදොස් කිරීම සඳහා විශේෂයෙන් උපක්රමශීලී විය හැකිය:
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();
}
මෙය වැරදි ඇයි? Iterator වාරණය ඇත්ත වශයෙන්ම ක්රියාත්මක වන තෙක් 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 ධාවන වේලාව පසුව මෙම දෝෂය හඳුනාගෙන එය ශුන්ය විරූපණ ව්යතිරේකයක් බවට පත් කරයි.
ශුන්ය දර්ශකයක් සහ ශුන්ය යොමු කිරීමක් යන දෙකම අවලංගු කිරීම එකම ව්යතිරේකයක් ඇති කරන්නේ එබැවිනි.
දෙවන කරුණ ගැන කුමක් කිව හැකිද? Dereferencing ඕනෑම අථත්ය මතකයක් අඩුම පිටුවේ වැටෙන අවලංගු පහිටුම් දක්වනය එම මෙහෙයුම් පද්ධතිය දෝෂ ඇතිවිය හා එමගින් එම හැර.
මෙය අර්ථවත් වන්නේ ඇයි? හොඳයි, අපට අඟල් දෙකක් අඩංගු ව්යුහයක් සහ ශුන්යයට සමාන කළමණාකරනය නොකළ දර්ශකයක් ඇතැයි සිතමු. අපි ව්යුහයේ දෙවන අන්තය අවලංගු කිරීමට උත්සාහ කරන්නේ නම්, CLRශුන්ය ස්ථානයේ ඇති ගබඩාවට ප්රවේශ වීමට උත්සාහ නොකරනු ඇත; එය හතරවන ස්ථානයේ ගබඩාවට පිවිසෙනු ඇත. නමුත් තර්කානුකූලව මෙය ශුන්ය විරූපණයකි, මන්ද අප එම ලිපිනයට ශුන්ය හරහා පිවිසෙන බැවිනි .
ඔබ අනාරක්ෂිත කේතයක් සමඟ වැඩ කරන්නේ නම් සහ ඔබට ශුන්ය විරූපණ ව්යතිරේකයක් ලැබෙන්නේ නම්, වරදකාරී දර්ශකය අහෝසි නොවිය යුතු බව මතක තබා ගන්න. එය පහළම පිටුවෙහි ඕනෑම ස්ථානයක් විය හැකි අතර මෙම ව්යතිරේකය නිපදවනු ඇත.
මෙම NullReference Exceptionසඳහා දෘශ්ය මූලික දී එක් වෙනස් නැත C # . සියල්ලට පසු, ඔවුන් දෙදෙනාම වාර්තා කරන්නේ .NET රාමුවේ අර්ථ දක්වා ඇති එකම ව්යතිරේකය ඔවුන් දෙදෙනාම භාවිතා කරන බවයි. දෘශ්ය මුලිකාංගයට අනන්ය වූ හේතු දුර්ලභ ය (සමහර විට එකක් පමණි).
මෙම පිළිතුර දෘශ්ය මූලික යෙදුම්, වාක්ය ඛණ්ඩය සහ සන්දර්භය භාවිතා කරයි. භාවිතා කරන උදාහරණ අතීත ස්ටැක් පිටාර ගැලීම් ප්රශ්න විශාල ගණනකින් පැමිණේ. මෙය භාවිතා කර අදාළ වන්නේ උපරිම ආකාරයේ බොහෝ විට තනතුරු දක්නට අවස්ථාවන්. අවශ්ය අය සඳහා තව ටිකක් පැහැදිලි කිරීමක් සපයනු ලැබේ. ඔබේ සමාන උදාහරණයක් වේ ඉතා ඉඩ මෙතන ලැයිස්තුගත.
සටහන:
NullReferenceException(NRE) ඇතිවීමට හේතුව , එය සොයා ගන්නේ කෙසේද, එය නිවැරදි කරන්නේ කෙසේද සහ එය වළක්වා ගන්නේ කෙසේද යන්න තේරුම් ගැනීමට ඔබට උදව් කිරීමට අදහස් කෙරේ . NRE බොහෝ ආකාරවලින් සිදුවිය හැකි බැවින් මෙය ඔබගේ එකම හමුවීම විය නොහැක."වස්තුව නිදසුනකට සකසා නැත" යන පණිවිඩයෙන් අදහස් කරන්නේ ඔබ ආරම්භ කර නොමැති වස්තුවක් භාවිතා කිරීමට උත්සාහ කරන බවයි. මෙය මෙයින් එකක් දක්වා උනු වේ:
ගැටළුව වස්තු යොමු කිරීමක් වන බැවින් Nothing, පිළිතුර වන්නේ ඒවා පරීක්ෂා කර ඒවා කුමන එකක් දැයි සොයා බැලීමයි. එය ආරම්භ නොකිරීමට හේතුව තීරණය කරන්න. විවිධ විචල්යයන් මත මූසිකය රඳවා තබා ගන්න. විෂුවල් ස්ටුඩියෝ (වීඑස්) ඒවායේ අගයන් පෙන්වනු ඇත - වැරදිකරු වනු ඇත Nothing.

අදාළ කේතයෙන් ඔබ උත්සාහ කරන්න / අල්ලා ගන්න බ්ලොක් ඉවත් කළ යුතුය, විශේෂයෙන් Catch block හි කිසිවක් නොමැති තැන. මෙය ඔබේ කේතය වස්තුවක් භාවිතා කිරීමට උත්සාහ කරන විට එය බිඳ වැටීමට හේතු වේ Nothing. මෙය ඔබට අවශ්ය වන්නේ එය ගැටලුවේ නිශ්චිත ස්ථානය හදුනා ගන්නා අතර එයට හේතු වන වස්තුව හඳුනා ගැනීමට ඔබට ඉඩ සලසයි.
ඒ MsgBoxදුම්රිය අල්ලා දී ප්රදර්ශනය කරන Error while...පොඩි උපකාරයක් වනු ඇත. මෙම ක්රමය ඉතා නරක ස්ටැක් පිටාර ගැලීමේ ප්රශ්න වලට ද මග පාදයි , මන්ද ඔබට සත්ය ව්යතිරේකය, සම්බන්ධ වස්තුව හෝ එය සිදු වන කේත රේඛාව පවා විස්තර කළ නොහැක.
ඔබ ද භාවිතා කළ හැකිය Locals Window( > වාසීන් - -> වින්ඩෝස් ඩිබග් ඔබගේ වස්තූන් පරීක්ෂා කිරීමට).
ගැටලුව කුමක්ද සහ කොතැනදැයි ඔබ දැනගත් පසු, එය නව ප්රශ්නයක් පළ කිරීමට වඩා පහසුවෙන් විසඳා ගැනීමට පහසුය.
මෙයද බලන්න:
Dim reg As CashRegister
...
TextBox1.Text = reg.Amount ' NRE
ගැටළුව වන්නේ DimCashRegister වස්තුවක් නිර්මාණය නොකිරීමයි ; එය ප්රකාශ කරන්නේ 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
සටහන: ඉදිකිරීම්කරු ( ) ද ඇතුළුව ක්රියා පටිපාටියක් තුළ නැවත භාවිතා නොකරන්න :DimSub New
Private reg As CashRegister
'...
Public Sub New()
'...
Dim reg As New CashRegister
End Sub
මෙය දේශීය විචල්යයක් නිර්මාණය කරනු ඇත reg, එය පවතින්නේ එම සන්දර්භය තුළ පමණි (උප). මෙම regමොඩියුලය මට්ටමේ විචල්ය Scopeඔබ සෑම තැනකම වෙන දේහය භාවිතා කරන Nothing.
NewNullReference Exceptionsසමාලෝචනය කරන ලද තොග පිටාර ගැලීමේ ප්රශ්න වල # 1 හේතුව ක්රියාකරු අතුරුදහන් වීමයි.දෘශ්ය මුලික ක්රියාවලිය නැවත නැවත භාවිතා කිරීමෙන් පැහැදිලි කිරීමට උත්සාහ කරයි
New:Newක්රියාකරු භාවිතා කිරීම මඟින් නව වස්තුවක් නිර්මාණය කරනSub Newඅතර ඔබේ වස්තුවට වෙනත් ඕනෑම ආරම්භයක් කළ හැකි ඉදිකිරීම්කරු - ඇමතුම් .
පැහැදිලිව කිවහොත් Dim(හෝ Private) ප්රකාශ කරන්නේ විචල්යයක් සහ එය පමණි Type. මෙම විෂය පථය එය සමස්ත මොඩියුලය / පන්තිය සඳහා පවතින හෝ පටිපාටිය සඳහා දේශීය යන්න - - එකේම මගින් තීරණය කරනු ඇති එය ප්රකාශයට පත් කර ඇත. Private | Friend | Publicප්රවේශ මට්ටම නිර්වචනය කරයි, විෂය පථය නොවේ .
වැඩි විස්තර සඳහා බලන්න:
අරා ද ක්ෂණික කළ යුතුය:
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) {}
සටහන: VS 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
එක්කෝ ක්රියා පටිපාටියේ ප්රති N ලයක් ලෙස එන්.ආර්.ඊ එකක් ලැබෙනු ඇත 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 Server, 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දේශීය විචල්යයක් බැවින්, මෙය සිදුවිය හැකි බවට IDE ඔබට අනතුරු අඟවයි :

මොඩියුලය / පන්ති මට්ටමේ විචල්යයක් ලෙස ප්රකාශයට පත් කළ විට මෙන් 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ප්රති access ල එයට ප්රවේශ වීමට උත්සාහ කරයි. තවත් විභව ගැටළුවක් වන්නේ ItemsSQL හි 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
FillRowsපරීක්ෂා කළ හැකි බලපෑමට ලක්වූ සංඛ්යාව ආපසු ලබා දෙන ශ්රිතයකි :
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ඇත, නමුත් එය SQL හෝ දත්ත සමුදා වගුවෙන් නම් විග්රහ නොකරයි. එහි ds.Tables("TICKET_RESERVATION")ප්රති As ලයක් ලෙස නොපවතින වගුවක් සඳහන් කරයි.
මෙම පිළියමක් දර්ශකය විසින් මේසය අදාල, එකම ය:
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)
වෙනත් දේ අතර, පරිශීලකයා විසින් UI පාලක එකක් හෝ වැඩි ගණනක් තුළ යමක් තෝරාගෙන නොමැති බව මෙම කේතය අපේක්ෂා නොකරයි. ListBox1.SelectedItemකරනවා වෙන්න පුළුවන් Nothing, ඒ නිසා ListBox1.SelectedItem.ToStringයම් NRE හේතු වනු ඇත.
පිළියමක්
දත්ත භාවිතා කිරීමට පෙර එය වලංගු කරන්න (එසේම Option StrictSQL පරාමිතීන් භාවිතා කරන්න ):
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
NRE ලබා ගැනීම සඳහා මෙය තරමක් පොදු ක්රමයකි. C # හි, එය කේතනය කර ඇති ආකාරය මත පදනම්ව, IDE විසින් Controlsවර්තමාන සන්දර්භය තුළ නොපවතින බව වාර්තා කරයි , නැතහොත් "ස්ථිතික නොවන සාමාජිකයෙකු සඳහන් කළ නොහැක". ඉතින්, යම් දුරකට, මෙය VB පමණක් වන තත්වයකි. එය අසාර්ථක කඳුරැල්ලකට හේතු විය හැකි නිසා එය ද සංකීර්ණ ය.
අරා සහ එකතු කිරීම් මේ ආකාරයෙන් ආරම්භ කළ නොහැක. මෙම ආරම්භක කේතය ඉදිකිරීම්කරු විසින් නිර්මාණය කිරීමට පෙරForm හෝ Controls. ප්රතිඵලයක් වශයෙන්:
somevarකිසිවක් ඇති නොවන නිසා පැවරුම වහාම NRE හේතු වනු ඇත .Textදේපලඅරාවෙහි මූලද්රව්යයන් පසුව යොමු කිරීමෙන් NRE එකක් ලැබෙනු ඇත. Form_Loadඅමුතු දෝෂයක් හේතුවෙන් ඔබ මෙය කරන්නේ නම් , එය සිදු වූ විට IDE විසින් ව්යතිරේකය වාර්තා නොකරනු ඇත. ඔබේ කේතය අරාව භාවිතා කිරීමට උත්සාහ කරන විට ව්යතිරේකය පසුව උත්පතන වේ. මෙම "නිහ silent ව්යතිරේකය" මෙම ලිපියේ සවිස්තරව දක්වා ඇත . අපගේ අරමුණු සඳහා, ප්රධාන දෙය නම්, පෝරමයක් ( Sub Newහෝ Form Loadසිදුවීමක්) නිර්මාණය කිරීමේදී යම් ව්යසනකාරී දෙයක් සිදු වූ විට , ව්යතිරේකයන් වාර්තා නොවීමට ඉඩ ඇති විට, කේතය ක්රියා පටිපාටියෙන් ඉවත් වී පෝරමය පෙන්වයි.
ඔබගේ Sub Newහෝ Form Loadසිද්ධියේ වෙනත් කිසිදු කේතයක් NRE පසු ක්රියාත්මක නොවන බැවින්, තවත් බොහෝ දේ ආරම්භ නොකර තබා ගත හැකිය.
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
අරාව කේතය තවමත් වනාන්තරයෙන් පිටත නොතිබිය හැකිය. බහාලුම් පාලනයක (a GroupBoxහෝ වැනි Panel) ඕනෑම පාලනයක් සොයාගත නොහැක Me.Controls; ඒවා එම මණ්ඩලයේ හෝ සමූහ බොක්ස් හි පාලන එකතුවෙහි ඇත. පාලක නාමය අක්ෂර වින්යාසය සහිත විට පාලනයක් ආපසු ලබා නොදෙනු ඇත ( "TeStBox2"). එවැනි අවස්ථාවන්හිදී, Nothingනැවත එම අරාවෙහි මූලද්රව්යයන් තුළ ගබඩා වනු ඇති අතර ඔබ එය යොමු කිරීමට උත්සාහ කරන විට NRE ප්රති result ලයක් වනු ඇත.
ඔබ සොයන දේ ඔබ දන්නා බැවින් මේවා දැන් සොයා ගැනීම පහසු විය යුතුය:

"බොත්තම් 2" වාසය කරන්නේ a 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ප්රති result ලයක් විය හැකිය ' යනුවෙන් IDE ඔබට අනතුරු අඟවන අවස්ථාවකි . ඔබ වෙනුවට, මෙම අනතුරු ඇඟවීම යටපත් කළ හැකිය Exit Functionසමග Return Nothing, නමුත් එම ගැටලුව විසඳන්නේ නැහැ. ප්රතිලාභයක් භාවිතා කිරීමට උත්සාහ කරන ඕනෑම දෙයක් someCondition = FalseNRE වලට හේතු වේ:
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' ට පසුව) එහි ප්රති a ලය ව්යතිරේකයකි .ExecuteReader. Catchකිසිවක් නොකළ පසු , Finallyපිරිසිදු කිරීම සිදු කිරීමට උත්සාහ කරයි, නමුත් ඔබට Closeශුන්ය DataReaderවස්තුවක් කළ නොහැකි බැවින් , නවතම ප්රති .ල NullReferenceException.
හිස් Catchකොටස යනු යක්ෂයාගේ ක්රීඩා පිටියයි. ඔහු Finallyබ්ලොක් එකට එන්.ආර්.ඊ ලබා ගන්නේ ඇයිද යන්න මෙම OP අවුල් විය . වෙනත් අවස්ථාවන්හිදී, හිස් Catchවීමක් නිසා තවත් බොහෝ දේ පහළට පහළට පිදුරු ගෑමට ඉඩ ඇති අතර ගැටළුව සඳහා වැරදි ස්ථානයේ වැරදි දේ දෙස බැලීමට ඔබට කාලය ගත කළ හැකිය. (ඉහත විස්තර කර ඇති "නිහ silent ව්යතිරේකය" එකම විනෝදාස්වාද වටිනාකමක් ලබා දෙයි.)
පිළියමක්
හිස් උත්සාහ කරන්න / ඇල්ලීමේ කුට්ටි භාවිතා නොකරන්න - කේත බිඳවැටීමට ඉඩ දෙන්න එවිට ඔබට අ) හේතුව හඳුනා ගැනීමට ආ) ස්ථානය හඳුනාගෙන ඇ) නිසි පිළියමක් යොදන්න. උත්සාහ කරන්න / අල්ලා ගන්න කුට්ටි ඒවා නිවැරදි කිරීමට අද්විතීය සුදුසුකම් ඇති පුද්ගලයාගෙන් ව්යතිරේකයන් සැඟවීමට අදහස් නොකෙරේ - සංවර්ධකයා.
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 ...
වරින් වර දැකිය හැකි කාරණා කිහිපයක් DGV සතුව ඇත:
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) NRE එකක් ඇති කරයි.
පිළියමක්
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හැකිය. විසඳුම සමාන ය, නමුත් එතරම් පැහැදිලි නැත. සලකා බලන්න:
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.ජෙට් බ්රේන්ස් හි නැවත පිරවීමේ මෙවලම මඟින් ඔබේ කේතයේ ඇති සෑම ස්ථානයක්ම ශුන්ය යොමු දෝෂයක් ඇතිවීමේ හැකියාව හඳුනාගනු ඇත. මෙම දෝෂය දෝෂ වල අංක එකේ ප්රභවය වන 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 පරාමිතියෙහි ඇත.
C # 8.0, 2019 යාවත්කාලීන කරන්න: අහෝසි කළ හැකි යොමු වර්ග
C # 8.0 හඳුන්වාදෙයි nullable යොමු වර්ග හා -nullable නොවන සමුද්දේශ වර්ග . එබැවින් NullReferenceException වළක්වා ගැනීම සඳහා පරීක්ෂා කළ යුත්තේ යොමු කළ හැකි යොමු වර්ග පමණි .
ඔබ විමර්ශන වර්ගයක් ආරම්භ කර නොමැති නම් සහ ඔබට එහි එක් ගුණාංගයක් සැකසීමට හෝ කියවීමට අවශ්ය නම්, එය NullReferenceException එකක් දමනු ඇත.
උදාහරණයක්:
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] අතර වෙනස දැන ගැනීම වැදගත්ය .
එබැවින්, ඔබ අගය වර්ග සමඟ කටයුතු කරන්නේ නම් , NullReferenceExceptions සිදුවිය නොහැක . විමර්ශන වර්ග සමඟ කටයුතු කිරීමේදී ඔබ සෝදිසියෙන් සිටිය යුතු වුවද !
නම යෝජනා කරන පරිදි යොමු යොමු වර්ග වලට පමණක් යොමු දැක්වීම් හෝ වචනාර්ථයෙන් කිසිවක් (හෝ 'ශුන්ය') වෙත යොමු කළ හැකිය. වටිනාකම් වර්ගවල සෑම විටම අගයක් අඩංගු වේ.
යොමු වර්ග (මේවා පරීක්ෂා කළ යුතුය):
අගය වර්ග (ඔබට මේවා නොසලකා හැරිය හැක):
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නොගැලපෙන වර්ග; a Carබවට පරිවර්තනය කළ නොහැක Book. මෙම වාත්තු කිරීම අසමත් වූ විට, asනැවත පැමිණේ null. මෙයින් mybookපසුව භාවිතා කිරීම a 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: වස්තු යොමු කිරීම වස්තුවක උදාහරණයකට සකසා නොමැත. වැඩසටහනේ දී. ප්රධාන ()
අතර කුමන හේතු වේ NullReferenceExceptions හා ප්රවේශයන් / වැලැක්විමට හදන්න එවැනි හැර වෙනත් පිළිතුරු ආමන්ත්රණය කර ඇත, දේ බොහෝ වැඩසටහන්කරුවන් තවමත් උගත් නැහැ ස්වාධීනව කරන්නේ කෙසේ ද යන්න යි එකතුකරන්න සංවර්ධන තුළ එවැනි ව්යතිරේකයන්.
විෂුවල් ස්ටුඩියෝ හි මෙය සාමාන්යයෙන් දෘශ්ය ස්ටුඩියෝ නිදොස්කරණයට ස්තූතියි .
පළමුව, නිවැරදි දෝෂය හසු වන බවට වග බලා ගන්න - බලන්න VS2010 හි 'System.NullReferenceException' බිඳ දැමීමට මා ඉඩ දෙන්නේ කෙසේද? සටහන 1
ඉන්පසු නිදොස් කිරීම (F5) සමඟ ආරම්භ කරන්න හෝ ක්රියාත්මක කිරීමේ ක්රියාවලියට [VS නිදොස්කරණය] අමුණන්න . සමහර විට එය භාවිතා කිරීම ප්රයෝජනවත් විය හැකි අතර Debugger.Break, එය නිදොස්කරණය දියත් කිරීමට විමසනු ඇත.
දැන්, NullReferenceException විසි කළ විට (හෝ පාලනයකින් තොරව) නිදොස් කිරීම සිදු වූ රේඛාව මත නිදොස්කරණය නතර වනු ඇත (ඉහත සඳහන් කළ රීතිය මතකද?). සමහර විට දෝෂය පහසුවෙන් හඳුනාගත හැකිය.
නිදසුනක් ලෙස, පහත දැක්වෙන පේළියේ ව්යතිරේකයට හේතු විය හැකි එකම කේතය වන්නේ myStringශුන්ය ලෙස තක්සේරු කළහොත් පමණි . ඔරලෝසු කවුළුව දෙස බැලීමෙන් හෝ ක්ෂණික කවුළුවේ ප්රකාශන ධාවනය කිරීමෙන් මෙය සත්යාපනය කළ හැකිය .
var x = myString.Trim();
පහත දැක්වෙන වැනි වඩා දියුණු අවස්ථාවන්හිදී, ප්රකාශන str1ශුන්යද නැතිනම් ශුන්යද යන්න තීරණය කිරීම සඳහා ප්රකාශන පරීක්ෂා කිරීම සඳහා ඉහත ක්රම වලින් එකක් (වොච් හෝ ක්ෂණික වින්ඩෝස්) භාවිතා කිරීමට ඔබට අවශ්ය වේ str2.
var x = str1.Trim() + str2.Trim();
වරක් එහිදී හැර විසි පිහිටා ඇත ඇත ඇත, එය හිස් අගයක් [වැරදි] හඳුන්වා දෙන ලදී එහිදී සොයා ගැනීමට සාමාන්යයෙන් හේතුව ආපස්සට අනවශ්ය ය -
ව්යතිරේකයේ හේතුව තේරුම් ගැනීමට අවශ්ය කාලය ගන්න. ශූන්ය ප්රකාශන සඳහා පරීක්ෂා කරන්න. එවැනි ශුන්ය ප්රකාශනවල ප්රති have ලයක් විය හැකි පෙර ප්රකාශන පරීක්ෂා කරන්න. බ්රේක්පොයින්ට් එකතු කර සුදුසු පරිදි වැඩසටහන හරහා පියවර තබන්න . නිදොස්කරණය භාවිතා කරන්න.
1 බ්රේක් ඔන් ත්රෝස් ඉතා ආක්රමණශීලී නම් සහ .NET හෝ තෙවන පාර්ශවීය පුස්තකාලයේ එන්පීඊ මත නිදොස්කරණය නතර වුවහොත්, අල්ලා ගත් ව්යතිරේකයන් සීමා කිරීම සඳහා බ්රේක් ඔන් පරිශීලක-හැන්ඩ්ල්ඩ් භාවිතා කළ හැකිය. මීට අමතරව, VS2012 Just My Code හඳුන්වා දෙන අතර එය සක්රීය කිරීමට මම නිර්දේශ කරමි.
ඔබ මගේ කේතය සක්රීය කර ඇති විට නිදොස්කරණය කරන්නේ නම්, හැසිරීම තරමක් වෙනස් වේ. Just My Code සක්රීය කර ඇති විට, නිදොස්කරණය මගේ කේතයෙන් පිටත විසි කරන සහ මගේ කේතය හරහා නොයන පළමු අවස්ථාව පොදු භාෂා ධාවන කාලය (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 එකක් දමනු ඇත. SaveChanges ()
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;}
}
දෝෂය සිදුවන්නේ වස්තුව සහ කේත පිටුපස පන්තිය යන දෙකම එකම නාම අවකාශයක ඇති විටය. මෙය නිවැරදි කිරීම සඳහා, Contact.aspx සඳහා වස්තු පන්තිය හෝ කේත පිටුපස පන්තිය නැවත නම් කරන්න.
හේතුව මට තවමත් විශ්වාස නැත. නමුත් ඕනෑම වස්තු පන්තියක් System.Web.UI.Page දීර් extend කරන සෑම අවස්ථාවකම මෙම දෝෂය ඇතිවේ.
සාකච්ඡාව සඳහා DbContext.saveChanges () හි NullReferenceException බලන්න.
යමෙකුට මෙම ව්යතිරේකය ලැබිය හැකි තවත් පොදු සිද්ධියක් වන්නේ ඒකක පරීක්ෂණ අතරතුර පන්ති සමච්චලයට ලක් කිරීමයි. භාවිතා කරන සමච්චල් කිරීමේ රාමුව කුමක් වුවත්, පන්ති ධූරාවලියේ සියලු සුදුසු මට්ටම් නිසි ලෙස සමච්චලයට ලක්වන බවට ඔබ සහතික විය යුතුය. විශේෂයෙන්, HttpContextපරීක්ෂණය යටතේ ඇති කේතය මගින් සඳහන් කර ඇති සියලුම ගුණාංග සමච්චලයට ලක් කළ යුතුය.
තරමක් වාචික උදාහරණයක් සඳහා " අභිරුචි බලය පැවරීම පරීක්ෂා කිරීමේදී විසි කරන ලද NullReferenceException " බලන්න .
මෙයට පිළිතුරු දීමට මට වෙනස් ඉදිරිදර්ශනයක් ඇත. මේ ආකාරයේ පිළිතුරු "එය වළක්වා ගැනීමට මට වෙන කුමක් කළ හැකිද? "
විවිධ ස්ථර හරහා වැඩ කරන විට , උදාහරණයක් ලෙස MVC යෙදුමක, පාලකයෙකුට ව්යාපාර මෙහෙයුම් ඇමතීමට සේවාවන් අවශ්ය වේ. එවැනි අවස්ථා වලදී 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();
}
}
"මම ඒ ගැන කුමක් කළ යුතුද" යන කාරණය සම්බන්ධයෙන් බොහෝ පිළිතුරු තිබිය හැකිය.
එවැනි දෝෂ තත්වයන් වැළැක්වීම පිළිබඳව වඩාත් "විධිමත්" මාර්ගය සංවර්ධනය අතර අදාළ කරන්නේ, කොන්ත්රාත් විසින් නිර්මාණය ඔබගේ කේතය දී. මෙම මාර්ගයෙන් ඔබ මාලාවක් පන්තියට අවශ්ය invariants , සහ / හෝ කාර්යය / ක්රමය පූර්ව කොන්දේසි හා postconditions සංවර්ධනය අතර, ඔබේ පද්ධතිය මත.
කෙටියෙන් කිවහොත්, පන්ති invariants සාමාන්ය භාවිතය උල්ලංඝනය වීම නොවන බව ඔබේ පන්තියේ සමහර සීමාවන් වනු ඇත (සහ ඒ නිසා, පන්ති බව සහතික නෑ අස්ථාවර දී ලබා). පූර්ව කොන්දේසි යනු ශ්රිතයකට / ක්රමයකට ආදානය ලෙස ලබා දී ඇති දත්ත යම් යම් සීමාවන් අනුගමනය කළ යුතු අතර ඒවා කිසි විටෙකත් උල්ලං late නය නොකළ යුතු අතර පශ්චාත් කොන්දේසි යන්නෙන් අදහස් වන්නේ ශ්රිතයක් / ක්රම ප්රතිදානයක් මඟින් කිසි විටෙකත් ඒවා උල්ලං without නය නොකර නැවත සකස් කළ යුතු බවයි. කොන්ත්රාත් කොන්දේසි යුතු නැහැ දෝෂය-නිදහස් වැඩසටහන ක්රියාත්මක තුළ උල්ලංඝණය කළ, ඒ නිසා කොන්ත්රාත් විසින් නිර්මාණය ප්රායෝගිකව දෝශනිරාකරණ වාර්ථා ආකාරයෙන්, ලබන අතර, පරීක්ෂා කෙරේ නිකුත් අක්රිය , සංවර්ධිත පද්ධතිය උපරිම කාර්යක්ෂමතාව.
මේ ආකාරයෙන්, NullReferenceExceptionනියම කර ඇති අවහිරතා උල්ලං of නය කිරීමේ ප්රති results ල වන අවස්ථා වළක්වා ගත හැකිය . නිදසුනක් ලෙස, ඔබ Xපන්තියක වස්තු දේපලක් භාවිතා කර පසුව එහි එක් ක්රමයක් භාවිතා කිරීමට උත්සාහ Xකර ශුන්ය අගයක් දරන්නේ නම්, මෙය මෙයට හේතු වනු ඇත NullReferenceException:
public X { get; set; }
public void InvokeX()
{
X.DoSomething(); // if X value is null, you will get a NullReferenceException
}
නමුත් ඔබ "දේපල X කිසි විටෙකත් ශුන්ය අගයක් නොතිබිය යුතුය" යන්න ක්රමවේදය පූර්ව කොන්දේසියක් ලෙස සකසන්නේ නම්, ඔබට කලින් විස්තර කර ඇති තත්වය වළක්වා ගත හැකිය:
//Using code contracts:
[ContractInvariantMethod]
protected void ObjectInvariant ()
{
Contract.Invariant ( X != null );
//...
}
මෙම හේතුව නිසා .NET යෙදුම් සඳහා කේත කොන්ත්රාත් ව්යාපෘතිය පවතී.
විකල්පයක් ලෙස, කොන්ත්රාත්තුව අනුව සැලසුම් කිරීම ප්රකාශයන් භාවිතා කළ හැකිය .
යාවත්කාලීන කිරීම: බර්ට්රන්ඩ් මේයර් විසින් අයිෆල් ක්රමලේඛන භාෂාව නිර්මාණය කිරීම සම්බන්ධව මෙම යෙදුම භාවිතා කළ බව සඳහන් කිරීම වටී .
NullReferenceExceptionඅපි ශුන්ය වස්තුවක ගුණාංග වෙත ප්රවේශ වීමට උත්සාහ කරන විට හෝ නූල් අගයක් හිස් වූ විට අපි නූල් ක්රමවලට ප්රවේශ වීමට උත්සාහ කරන විට A විසි කරනු ලැබේ.
උදාහරණයක් වශයෙන්:
හිස් නූලක නූල් ක්රමයක් ප්රවේශ වූ විට:
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
"මයික්රොසොෆ්ට් කේත කොන්ත්රාත්තු" ඇත, එහිදී ඔබ සින්ටැක්ස් භාවිතා Contract.Requires(obj != null)කරන අතර එමඟින් ඔබට ධාවන කාලය සහ පරික්ෂා කිරීම සිදු කරයි: කේත කොන්ත්රාත්තු හඳුන්වා දීම .
"PostSharp" ද ඇත, එමඟින් ඔබට මෙවැනි ගුණාංග භාවිතා කිරීමට ඉඩ ලබා දේ:
public void DoSometing([NotNull] obj)
එය කිරීමෙන් සහ ඔබගේ ගොඩනැගීමේ ක්රියාවලියේ PostSharp කොටසක් බවට පත් කිරීමෙන් ධාවන වේලාවේදී අහෝසි වේදැයි objපරීක්ෂා කරනු ලැබේ. බලන්න: PostSharp null check
සරල කේත විසඳුම
නැතහොත් ඔබට සෑම විටම සරල පැරණි කේත භාවිතා කර ඔබේම ප්රවේශය කේත කළ හැකිය. උදාහරණයක් ලෙස මෙහි ඔබට ශූන්ය යොමු කිරීම් භාවිතා කළ හැකි ව්යුහයකි. එය එකම සංකල්පයකින් පසුව ආදර්ශනය කර ඇත 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ලිපිනය isnull`.
එය විශිෂ්ට ලක්ෂණයකි, නමුත් එය ඔබට අඩු තොරතුරු ලබා දෙයි. 4 න් කුමන ශුන්යද යන්න එය පැහැදිලි නොකරයි.
Nullable වැනි ගොඩනගා තිබේද?
C # සඳහා කදිම කෙටිමං ඇත Nullable<T>, එවැනි වර්ගයට පසුව ප්රශ්නාර්ථ ලකුණක් තැබීමෙන් ඔබට අහෝසි කළ හැකිය int?.
C # හි NotNull<T>ඉහත ව්යුහය හා සමාන කෙටිමං එකක් තිබේ නම් හොඳයි , සමහර විට විශ්මයජනක ලක්ෂ්යය (!) එවිට ඔබට එවැනි දෙයක් ලිවිය හැකිය : public void WriteName(Person! person).
සිත්ගන්නා කරුණ නම්, මෙම පිටුවේ කිසිදු පිළිතුරක අද්දර අවස්ථා දෙක ගැන සඳහන් නොවේ, මම ඒවා එකතු කළහොත් කිසිවෙකු සිතන්නේ නැත:
.NET හි ඇති සාමාන්ය ශබ්දකෝෂ නූල්-ආරක්ෂිත නොවන අතර සමහර විට ඔබ සමගාමී නූල් දෙකකින් යතුරකට ප්රවේශ වීමට උත්සාහ NullReferenceකරන KeyNotFoundExceptionවිට ඒවා සමහර විට හෝ ඊටත් වඩා (නිතර නිතර) විසි කළ හැකිය . ව්යතිරේකය මෙම නඩුවේ තරමක් නොමඟ යවන සුළුය.
කේතයක් NullReferenceExceptionමඟින් විසි කරනු ලැබුවහොත් unsafe, ඔබට ඔබේ දර්ශක විචල්යයන් දෙස බලා ඒවා IntPtr.Zeroහෝ වෙනත් දෙයක් පරීක්ෂා කරන්න. එය එකම දෙයයි ("ශුන්ය දර්ශක ව්යතිරේකය"), නමුත් අනාරක්ෂිත කේතයේ විචල්යයන් බොහෝ විට අගය වර්ග / අරා යනාදිය වෙතට දමනු ලැබේ. තවද ඔබ ඔබේ හිස බිත්තියට එබීමෙන් වටිනාකමක් ඇති වර්ගයක් මෙය විසි කරන්නේ කෙසේදැයි කල්පනා කරයි ව්යතිරේකය.
(අනාරක්ෂිත කේතයක් ඔබට අවශ්ය නම් මිස භාවිතා නොකිරීමට තවත් හේතුවක්)
nullකුමන ආකාරයෙන් වෙනස් වේද?
C # 6 හි ශුන්ය-කොන්දේසි සහිත ක්රියාකරුවන් භාවිතා කර ඔබට NullReferenceException පිරිසිදු ආකාරයකින් සවි කළ හැකි අතර ශුන්ය චෙක්පත් හැසිරවීමට අඩු කේතයක් ලියන්න.
සාමාජික ප්රවේශයක් (?.) හෝ දර්ශක (? [) මෙහෙයුමක් කිරීමට පෙර එය ශුන්ය ලෙස පරීක්ෂා කිරීමට භාවිතා කරයි.
උදාහරණයක්
var name = p?.Spouse?.FirstName;
සමාන වේ:
if (p != null)
{
if (p.Spouse != null)
{
name = p.Spouse.FirstName;
}
}
මෙහි ප්රති result ලය වනුයේ p ශුන්ය වූ විට හෝ p.Spouse ශුන්ය වූ විට නම ශුන්ය වනු ඇත.
එසේ නොමැතිනම් විචල්ය නාමයට p.Spouse.FirstName හි අගය පවරනු ලැබේ.
වැඩි විස්තර සඳහා: ශුන්ය-කොන්දේසි සහිත ක්රියාකරුවන්
"වස්තු යොමු කිරීම වස්තුවක නිදසුනකට සකසා නැත" යන දෝෂ රේඛාවේ සඳහන් වන්නේ ඔබ වස්තු යොමු කිරීම සඳහා නිදර්ශන වස්තුව පවරා නොමැති බවත් තවමත් ඔබ එම වස්තුවේ නිසි / ක්රම වෙත ප්රවේශ වන බවත් ය.
උදාහරණයක් ලෙස: ඔබට myClass නමින් පන්තියක් ඇති බවත් එහි එක් දේපල prop1 අඩංගු බවත් කියමු.
public Class myClass
{
public int prop1 {get;set;}
}
දැන් ඔබ පහත දැක්වෙන ආකාරයට වෙනත් පන්තියකට මෙම prop1 වෙත පිවිසෙමින් සිටී:
public class Demo
{
public void testMethod()
{
myClass ref = null;
ref.prop1 = 1; //This line throws error
}
}
පංතියේ මයික්ලාස් පිළිබඳ සඳහන ප්රකාශයට පත් කර ඇති නමුත් ක්ෂණිකව නොපවතින නිසා හෝ එම පන්තියේ ජනමත විචාරණය සඳහා වස්තුවක නිදසුනක් පවරා නොමැති නිසා ඉහත පේළියේ දෝෂයක් ඇතිවේ.
මෙය නිවැරදි කිරීම සඳහා ඔබ ක්ෂණිකව කළ යුතුය (එම පන්තියේ යොමු කිරීම සඳහා වස්තුව පවරන්න).
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 නිවැරදි කිරීමට පහසුම ක්රමය ක්රම දෙකක් ඇත. ඔබට ස්ක්රිප්ට් එකක් අමුණා ඇති ගේම් ඕබෙක්ට් එකක් තිබේ නම් සහ ආර්බී (රිගිඩ්බෝඩි) නම් විචල්යයක් තිබේ නම්, ඔබ ඔබේ ක්රීඩාව ආරම්භ කරන විට මෙම විචල්යය ශුන්ය වනු ඇත.
පරිගණකයේ එම විචල්යයේ දත්ත ගබඩා කර නොමැති නිසා ඔබට NullReferenceExeption එකක් ලැබෙන්නේ මේ නිසා ය.
මම උදාහරණයක් ලෙස RigidBody විචල්යයක් භාවිතා කරමි.
අපට ක්රම කිහිපයකින් දත්ත සැබවින්ම පහසුවෙන් එකතු කළ හැකිය:
rb = GetComponent<Rigidbody>();Start()හෝ Awake()කාර්යයන් යටතේ වඩාත් හොඳින් ක්රියාත්මක වේ. rb = AddComponent<RigidBody>(); වැඩිදුර සටහන්: ඔබේ වස්තුවට [RequireComponent(typeof(RigidBody))]සං component ටකයක් එක් කිරීමට ඔබට අවශ්ය නම් සහ එකක් එකතු කිරීමට ඔබට අමතක වී ඇත්නම්, ඔබට ඔබේ පන්ති ප්රකාශයට ඉහළින් ටයිප් කළ හැකිය (ඔබගේ සියලු භාවිතයන්ට වඩා අඩු ඉඩ).
විනෝද වෙමින් විනෝද ක්රීඩා කරන්න!
මෙම ව්යතිරේකය විසි කළ හැකි පොදු අවස්ථා අපි සලකා බලන්නේ නම්, ඉහළින් ඇති වස්තුව සමඟ ගුණාංග වෙත ප්රවේශ වීම.
උදා:
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
මෙය මූලික වශයෙන් ශුන්ය යොමු ව්යතිරේකයකි . ලෙස මයික්රොසොෆ්ට් states-
ඔබ අගය අවලංගු වන වර්ගයක සාමාජිකයෙකුට ප්රවේශ වීමට උත්සාහ කරන විට NullReferenceException ව්යතිරේකය විසි කරනු ලැබේ.
එයින් අදහස් වන්නේ කිසියම් වටිනාකමක් නැති සහ යම් කාර්යයක් කිරීමට අප එම සාමාජිකයා පත් කරන්නේ නම් පද්ධතිය නිසැකවම පණිවිඩයක් විසි කර කියනු ඇත-
"හේයි ඉන්න, එම සාමාජිකයාට කිසිදු වටිනාකමක් නැති නිසා ඔබ එය භාර දෙන කාර්යය ඉටු කළ නොහැක."
ව්යතිරේකය විසින්ම යමක් යොමු කරනු ලබන නමුත් ඒවායේ වටිනාකම නියම කර නොමැති බව පවසයි. එබැවින් මෙය ඇඟවෙන්නේ අගය වර්ග භාවිතා කළ නොහැකි බැවින් යොමු වර්ග භාවිතා කරන විට පමණි.
අපි අගය වර්ගයේ සාමාජිකයන් භාවිතා කරන්නේ නම් NullReferenceException සිදු නොවේ.
class Program
{
static void Main(string[] args)
{
string str = null;
Console.WriteLine(str.Length);
Console.ReadLine();
}
}
ඉහත කේතය මඟින් ශුන්ය අගයක් සහිත සරල නූලක් පෙන්වයි .
දැන්, මම වැල දිග මුද්රණය කිරීමට උත්සාහ කරන විට, STR , මම ලබා ගන්නේ කෙසේද වර්ගය 'System.NullReferenceException' ක unhandled ව්යතිරේකයක් පණිවිඩය සාමාජික නිසා 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");
}
}
ඉහත කේතය සඳහා සම්පාදකයා විසින් විචල්ය obj නියම කර නොමැති බවට දෝෂයක් මතු කරයි, එයින් ඇඟවෙන්නේ අපගේ විචල්යයට ශුන්ය අගයන් හෝ කිසිවක් නොමැති බවයි. ඉහත කේතය සඳහා සම්පාදකයා විසින් විචල්ය obj නියම කර නොමැති බවට දෝෂයක් මතු කරයි, එයින් ඇඟවෙන්නේ අපගේ විචල්යයට ශුන්ය අගයන් හෝ කිසිවක් නොමැති බවයි.
NullReferenceException පැන නගින්නේ වස්තුවේ වටිනාකම පරික්ෂා නොකිරීමේ අපගේ දෝෂය හේතුවෙනි. කේත සංවර්ධනයේදී අපි බොහෝ විට වස්තු අගයන් පරික්ෂා නොකරමු.
අපගේ වස්තූන් ක්ෂණිකව දැක්වීමට අමතක වූ විට ද එය පැන නගී. ආපසු හැරවීමට හෝ ශුන්ය අගයන් සැකසීමට හැකි ක්රම, ගුණාංග, එකතු කිරීම් ආදිය භාවිතා කිරීම ද මෙම ව්යතිරේකයට හේතුව විය හැකිය.
මෙම කීර්තිමත් ව්යතිරේකය වළක්වා ගැනීම සඳහා විවිධ ක්රම සහ ක්රම තිබේ:
පැහැදිලිව පරීක්ෂා කිරීම: වස්තූන්, ගුණාංග, ක්රම, අරා සහ එකතු කිරීම් අහෝසි දැයි පරීක්ෂා කිරීමේ සම්ප්රදායට අප අනුගත විය යුතුය. If-else if-else වැනි කොන්දේසි සහිත ප්රකාශ භාවිතා කරමින් මෙය සරලව ක්රියාත්මක කළ හැකිය.
ව්යතිරේකය හැසිරවීම: මෙම ව්යතිරේකය කළමනාකරණය කිරීමේ වැදගත් ක්රමයක්. සරල උත්සාහක-අවසාන-වාරණ භාවිතා කිරීමෙන් අපට මෙම ව්යතිරේකය පාලනය කළ හැකි අතර එහි ලොගයක් පවත්වා ගත හැකිය. ඔබේ යෙදුම නිෂ්පාදන අවධියේ සිටින විට මෙය ඉතා ප්රයෝජනවත් වේ.
ශුන්ය ක්රියාකරුවන්: වස්තු, විචල්යයන්, ගුණාංග සහ ක්ෂේත්ර සඳහා අගයන් සැකසීමේදී ශුන්ය සමතුලිත ක්රියාකරු සහ ශුන්ය කොන්දේසි සහිත ක්රියාකරුවන් ද ප්රයෝජනවත් ලෙස භාවිතා කළ හැකිය.
නිදොස්කරණය: සංවර්ධකයින් සඳහා, අප සමඟ නිදොස් කිරීමේ විශාල ආයුධය අප සතුව ඇත. සංවර්ධන මුහුණුවර තුළ අප NullReferenceException වලට මුහුණ දී ඇත්නම්, අපට නිදොස්කරණය භාවිතා කර ව්යතිරේකයේ ප්රභවය ලබා ගත හැකිය.
සාදන ලද ක්රමය: GetValueOrDefault (), IsNullOrWhiteSpace () සහ IsNullorEmpty () වැනි පද්ධති ක්රම මඟින් ශුන්යයන් පරික්ෂා කර ශුන්ය අගයක් තිබේ නම් පෙරනිමි අගය ලබා දේ.
දැනටමත් මෙහි හොඳ පිළිතුරු බොහොමයක් තිබේ. ඔබට මගේ බ්ලොග් අඩවියේ උදාහරණ සමඟ වඩාත් සවිස්තරාත්මක විස්තරයක් පරීක්ෂා කළ හැකිය .
මෙයද උපකාරී වේ යැයි සිතමු!
ගොඩනැගීම සුරැකීමේදී හෝ සම්පාදනය කිරීමේදී යමෙකුට මෙම පණිවිඩය ලැබෙන්නේ නම්, සියලු ලිපිගොනු වසා දමා සම්පාදනය කර සුරැකීමට ඕනෑම ගොනුවක් විවෘත කරන්න.
මට හේතුව වූයේ මම ගොනුව නැවත නම් කර තිබීම සහ පැරණි ගොනුව තවමත් විවෘතව තිබීමයි.