NullReferenceException İstisna nədir və onu necə düzəltmək olar?

Kod var və icra edildikdə, bir NullReferenceException salır, deyir:

Nümunə istinad obyektin nümunəsinə deyil.

Bu nə deməkdir və bu səhvəni düzəltmək üçün nə edə bilərəm?

1878
11 янв. Jan Solunders tərəfindən 11 yanvarda təyin olundu 2011-01-11 19:48 '11 at 19:48 2011-01-11 19:48
@ 34 cavab
  • 1
  • 2

Bunun səbəbi nədir?

Aşağı xətt

null olanı (və ya VB.NET-də Nothing ) istifadə etməyə çalışırsınız. Bu, ya dəyərini null təyin etdiyiniz deməkdir və ya heç bir şeyə heç bir şey qoymursunuz.

Hər şey kimi, null bypasses. "A" üsulunda null olarsa, "B" metodu "A" üsuluna null dəyərini keçə bilər.

null müxtəlif dəyərlərə malik ola bilər:

  1. Yeniliksiz olan obyektiv dəyişənlər və buna görə bir şey göstərmirlər. Bu halda, NullReferenceException belə obyektlərin xüsusiyyətlərinə və ya üsullarına, bu bir NullReferenceException səbəb olur.
  2. Geliştirici heç bir mənalı dəyər olmadığını göstərmək üçün qəsdən null istifadə edir. Qeyd edək ki, C # -də dəyişənlər üçün null data növləri (məsələn, verilənlər bazası cədvəlləri null dəyərli sahələrə malik ola bilər) ilə bağlı konsepsiyaya malikdir - bunları dəyər kimi olmadığını göstərmək üçün null təyin edə bilərsiniz, məsələn int? a = null; int? a = null; int? a = null; sual işarəsi dəyişən a dəyərində null dəyərinin saxlanılmasına icazə verildiyini göstərir. Bunu if (a.HasValue) {...}if (a==null) {...} ilə yoxlaya bilərsiniz. Bu nümunə kimi isteğe bağlı dəyişənlər a.Value vasitəsilə açıq və ya adi olaraq, a .
    Qeyd edək ki, a.Value vasitəsilə a.Value InvalidOperationException əvəzinə bir InvalidOperationException əvəzinə null - əvvəlcədən yoxlamaq lazımdır, yəni NULL variantında int b; ilə başqa bir dəyişən varsa int b; if (a.HasValue) { b = a.Value; } if (a.HasValue) { b = a.Value; } if (a.HasValue) { b = a.Value; } if (a.HasValue) { b = a.Value; } və ya daha qısa, if (a != null) { b = a; } if (a != null) { b = a; } if (a != null) { b = a; } if (a != null) { b = a; } .

Bu yazının qalan hissəsində bir çox proqramçı tez-tez bir NullReferenceException gətirib çıxara bilər ki, səhvlər daha ətraflı təsvir edir.

Daha dəqiq bir şəkildə

Bir NullReferenceException bir işləmə müddəti həmişə eyni şey deməkdir: bir keçid istifadə etməyə çalışırsınız və link başlanmadı (ya da bir dəfə başlatılmış, lakin artıq başlanmadı).

Bu, referansın null olduğu anlamına gelir ve null yoluyla elementlere (metodlar kimi) erişemezsiniz. Ən sadə vəziyyət:

 string foo = null; foo.ToUpper(); 

NullReferenceException ikinci satırda səbəb olur, çünki ToUpper() misal metodunu null göstərən string linkində ToUpper() .

ayıklama

NullReferenceException mənbəyini necə tapa bilərsiniz? Visual Studio'da ümumi nizamlama qaydaları tətbiq edildikdə, tam olaraq nizamlanacaq istisnanın özünü araşdırmaqla yanaşı, strategiyanın kəsilmə nöqtələrini yerləşdirin və dəyişənlərinizi adları üzərinə gedin, açın (Tez) Görünüş pəncərəsini açın və ya müxtəlif Yerli və Avtosalonlar kimi debug panelləri.

Bağlantının harada yerləşdiyini və ya quraşdırılmadığını bilmək istəyirsinizsə, adını sağ basın və "Bütün Bağları tapın" seçin. Sonra tapılan hər bir yerdə bir kəsmə nöqtəsi yerləşdirə və proqramınızı bir ayıklama qurğusu ilə əlaqələndirə bilərsiniz. Debugger belə bir kəsmə nöqtəsinə hər dəfə pozduqda, linkin qeyri-sıfır olmasını istəyirsən, dəyişənliyi yoxlayın və onu gözlədiyiniz zaman nümunəyə işarə etdiyinə əmin olun.

Beləliklə, proqram axını sonrasında, nümunənin sıfır olmaması və niyə səhv yükləndiyi bir yer tapa bilərsiniz.

Nümunələr

Bir istisnanın seçilə biləcəyi bəzi ümumi ssenarilər:

ümumi

 ref1.ref2.ref3.member 

Ref1 və ya ref2 və ya ref3 null olduqda, bir NullReferenceException . Bir problemi həll etmək istəsəniz, ifadəni sadəcə ekvivalentinə yenidən yazaraq sıfır olanını tapın:

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

Xüsusilə, HttpContext.Current.User.Identity.Name , HttpContext.Current null ola bilər və ya User mülkiyyəti boş ola bilər və ya Identity mülkiyyəti null ola bilər.

dolayı

 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. } } 

Əgər null (Person) istinadından qaçmaq istəməsəniz, onu (Kitab) obyekt qurucusuna başlamalısınız.

Nested obyekt əvvəlcədən

Yaddaş obyektlərin başlanğıclarına eynidır:

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

Tərcümə edir

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

new açar sözlər istifadə edildiyi müddətcə, yalnız new bir Book nümunəsi yaradır, ancaq Person yeni bir forması deyildir, beləliklə Author mülkiyyəti hələ də null .

İç içə kolleksiyanın təşəbbüskarı

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

Daxili kolleksiyaların təşəbbüskarı eyni davranır:

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

Tərcümə edir

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

new Person yalnız bir Person nümunəsini yaradır, ancaq Books toplusu hələ də null . Kolleksiya başlatma sintaksisi p1.Books üçün kolleksiya p1.Books , yalnız p1.Books.Add(...) çevirir.

array

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

Array elementləri

 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. 

Hard array

 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. 

Kolleksiya / Siyahı / Lüğət

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

Range dəyişən (dolayı / təxirə salınmış)

 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. 

Hadisələr

 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 } } 

Kötü adlandırma konvensiyaları:

Sahələri fərqli olaraq yerli olaraq aradınızsa, bu sahədə heç bir zaman başlanmadınız.

 public class Form1 { private Customer customer; private void Form1_Load(object sender, EventArgs e) { Customer customer = new Customer(); customer.Name = "John"; } private void Button_Click(object sender, EventArgs e) { MessageBox.Show(customer.Name); } } 

Bu, ön sxem müqaviləsini alt sətirlə tamamlayaraq həll edilə bilər:

 private Customer _customer; 

ASP.NET səhifə ömrü:

 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!"; } } 

ASP.NET Sessiya Dəyərləri

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

Boş ASP.NET MVC Viewer

ASP.NET MVC görünümündeki @Model əmlakına istinad edərkən bir istisna meydana @Model , return görünüşü olduqda Model , hərəkət metodunuzdakı dəyəri alır. Denetleyicinizden boş bir modeli (və ya model özelliğini) döndüğünüzde, görünümlerin eriştiği bir istisna oluşur:

 // 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 nəzarət və hadisələri yaratma proseduru

WPF denetimleri, InitializeComponent -a bir vizual ağacda görüntülendiği sıraya InitializeComponent yaradılır. NullReferenceException , hadisə işləyiciləri və s. NullReferenceException yaradılmış erkən yaradılmış nəzarətlər halında qaldırılacaq. NullReferenceException , gec yaradılmış nəzarətlərə aid olan InitializeComponent zamanı işə salınır.

Məsələn:

 <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> 

Burada comboBox1 əvvəl label1 . comboBox1_SelectionChanged 'label1' a istinad etməyə çalışırsa, hələ yaradılıb.

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

XAML-da (yəni label1 comboBox1 label1 comboBox1 label1 əvvəl comboBox1 , ən azı burada dizayn fəlsəfəsi problemlərinə comboBox1 , label1 ə imkan NullReferenceException .

Tökmə, as

 var myThing = someObject as Thing; 

Bu, bir InvalidCastException yüksəltməz, lakin başlamaması halında null qaytarır (və bəziObject özü sıfır olduqda). Bunu nəzərə alın.

LINQ FirstOrDefault () və SingleOrDefault ()

First()Single() sadə versiyaları heç bir şey olmadığında istisnalar istisna edir. Bu halda, "OrDefault" versiyaları null qaytarır. Bunu nəzərə alın.

hər biri üçün

foreach bir sıfır kolleksiyanı yinelemeye çalışırken atır. Ümumiyyətlə koleksiyonları geri qaytarma üsullarının gözlənilməz null nəticəsi.

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

Daha realist bir nümunə XML sənədindən olan qovşaqların seçilməsidir. Node tapılmadıqda atılır, amma ilk hata ayıklama bütün xüsusiyyətlərin etibarlı olduğunu göstərir:

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

Qaçmaq yolları

null dəyərini açıq şəkildə yoxlayır və null yox.

Bağlantının bəzən boş olmasını gözlədiyiniz halda, nümunə üzvlərinə daxil olmadan əvvəl onu boş saya bilərsiniz:

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

null dəyərini açıq şəkildə yoxlayın və u mənim dəyəri göstərin.

Bir nümunə qaytarmasını gözlədiyiniz üsullar, məsələn, aradığınız obyekt tapılmayana null geri dönə bilər. Əgər belədirsə, default dəyərini seçə bilərsiniz:

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

null metodun null dəyərini açıq şəkildə yoxlayıram və öz istisnəmi təyin edirəm.

Yalnız xüsusi bir istisna yaratmaq, yalnız onu zəng kodunda tutmaq üçün:

 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 əvvəl problemi həll etmək üçün heç bir Debug.Assert istifadə edin.

Bu üsulun mümkün ola biləcəyi inkişaf zamanı bilirsinizsə, lakin heç vaxt geri dönməyəcəksinizsə, Debug.Assert() istifadə Debug.Assert() mümkün olan ən qısa zamanda qırmaq üçün istifadə edə bilərsiniz:

 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. } 

Sürüm rejimində iş zamanı zamanı book == null olduqda, bu çek buraxılış quruluşunuzda NullReferenceException , NullReferenceException ni sıfırlamağa məcbur edir.

GetValueOrDefault() varsayılan bir dəyər təmin etmək üçün null dəyərlə dəyərlər növləri üçün GetValueOrDefault() istifadə edin.

 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 

Sıfır birləşmə operatorunu istifadə edin: ?? [C #] və ya If() [VB].

null qarşılaşdıqda default olaraq azaldın:

 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; } 

Sıfır vəziyyət operatorunu istifadə edin:? və ya ?[x] diziləri üçün (C # 6 və VB.NET 14-də mövcuddur):

Bəzən də təhlükəsiz naviqasiya və ya Elvis (formadan sonra) adlanır. Şərhin sol tərəfindəki ifadə NULL, onda sağ tərəf qiymətləndirilməyəcək və sıfır yerinə geri qaytarılacaq. Bu, belə hallar deməkdir:

 var title = person.Title.ToUpper(); 

Şəxsin adı yoxdursa, istisna qaldırır, çünki sıfır dəyəri olan bir əmlak üçün ToUpper ə zəng etməyə çalışır.

C # 5 və aşağıda bu qorunur:

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

İndi istisna istisna yerinə başlıq dəyişən null olacaq. C # 6 bu üçün daha qısa bir sintaksis təqdim edir:

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

Bu, varlıq dəyişəninin adının null olması ilə nəticələnəcək və şəxsin ToUpper çağırışı yerinə yetirilmir.

Əlbəttə, hələ də null üçün title yoxlamaq və ya sıfır birləşmə operatoru ilə birlikdə null vəziyyəti operatorunu istifadə etmək lazımdır ( ?? )

 // 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; 

Eynilə, dizilər üçün aşağıdakı kimi istifadə edə bilərsiniz:

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

Bu, aşağıdakıları yerinə yetirəcəkdir: myIntArray null olduqda, ifadə boş qaytarır və onu təhlükəsiz yoxlaya bilərsiniz. Bir sıra ehtiva edərsə, eyni şeyi elem = myIntArray[i]; : elem = myIntArray[i]; i elementi qaytarır.

Yineleyicilərdə sıfır sürüşmələri düzəltmək və sabitləşdirmək üçün xüsusi üsullar

C # "iterator blokları" (bəzi digər populyar dillərdə "generatorlar" adlanır) dəstəkləyir. İstisnalar şəklində istisnalar istisna olmaqla, təxirə salınmış icraata görə iterator bloklarında diskarifikasiya xüsusilə çətin ola bilər:

 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) { ... } 

Hər whatever nəticə MakeFrob , MakeFrob null whatever , MakeFrob MakeFrob atacaq. İndi bunun doğru bir şey olduğunu düşünürsünüz:

 // 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(); } 

Niyə bu yanlış? Iterator bloku foreach qədər həqiqətən başlamadığı üçün! GetFrobs sadəcə yineleyici bir iterator bloku başlayacaq bir obyekti qaytarır.

Null yoxlama yazaraq, null dereferencing qarşısını almaq, lakin boş nöqtə istisna hərəkət yineleme nöqtəsinə deyil, çağırma nöqtəsi, və bu çox səhv başqaları.

Düzgün düzəliş:

 // 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(); } 

Yəni iterator blokunun məntiqinə sahib olan xüsusi bir köməkçi metod yaradır və null yoxlamanı yerinə yetirən və iteratoru qaytaran açıq səth metodu. İndi, GetFrobs ilə, dərhal null yoxlama baş verir və sonra GetFrobsForReal ardıcıllığı təkrar edildikdə icra edilir.

LINQ for Objects link mənbəyini yoxlayırsınızsa, bu metodun hər yerdə istifadə edildiyini görəcəksiniz. Bu yazmaq üçün bir az daha çətindir, ancaq səhvlər ilə daha çox asanlıqla səhvlər düzəldir. Müəllifin rahatlığı üçün, çağıranın rahatlığı üçün kodunuzu optimallaşdırın .

Təhlükəli kodda sıfır fərqlər barədə qeyd

C #, adı nəzərdə tutulduğu kimi, çox təhlükəli olan "təhlükəli" rejimə malikdir, çünki yaddaş təhlükəsizliyi və növü təhlükəsizliyi təmin edən ənənəvi təhlükəsizlik mexanizmləri tətbiq edilmir. Əgər yaddaşın necə işlədiyini dərin başa düşmədiyiniz təqdirdə təhlükəli kod yazmırsınız .

Təhlükəli rejimdə iki mühüm həqiqəti bilmək lazımdır:

  • Null göstəricinin uzaqlaşdırılması sıfır istinad etmədən eyni istisna səbəb olur
  • Qeyri-sıfır olmayan göstəricinin kənarlaşdırılması bəzi hallarda bu istisna gətirə bilər

Bunun niyə başa düşdüyünü anlamaq üçün,. NET ilk növbədə sıfır fərq istisnaları yaradır. (Bu məlumatlar Windows əməliyyat sistemində tətbiq edilir. Digər əməliyyat sistemləri oxşar mexanizmlərdən istifadə edir.)

Yaddaş Windows-da virtualləşdirilmişdir; Hər bir proses əməliyyat sistemi tərəfindən izlənilən bir çox yaddaşdan "səhifələr "dən virtual yaddaş yerini əldə edir. Hər yaddaş səhifəsində necə istifadə olunanları müəyyənləşdirən bayraqlar quraşdırılır: oxumaq, yazmaq, yerinə yetirmək və s. Ən aşağı səhifə, "Əgər istifadə olunarsa bir səhv verin."

Null pointer və C #-də null istinad da məcburi sıfır nümunəvi dəyər kimi təqdim olunur və buna görə də yaddaşın müvafiq saxlanması ilə məhdudlaşmaq üçün hər hansı bir cəhd əməliyyat sisteminin bir səhv meydana gətirməsinə gətirib çıxarır. .NET iş zamanı bu səhvəni algılar və sıfır istisna halına çevirir.

Null pointer və null linki aradan qaldırmaq eyni istisna yaradır.

İkinci maddə nədir? Virtual yaddaşın ən aşağı səhifəsinə çarpan hər hansı bir etibarsız göstərici eyni əməliyyat sistemi səhvinə və buna görə eyni istisna səbəb olur.

Bu səbəb nədir? Güman ki, iki intsli bir quruluşumuz var və idarə edilməyən pointer sıfırdır. Əgər strukturda ikinci inti aradan qaldırmağa çalışırıqsa, CLR sıfır yerdəki saxlanmaya girişməyə çalışmaz; dördüncü yerdə depozitə çıxacaq. Amma məntiqi olaraq sıfır boşluqdur, çünki biz bu ünvanı sıfıra endiririk.

Təhlükəsiz bir kodla işləyirsinizsə və istisna istisnası istifadə edərək istisna edirsinizsə, zəhmət çəkən göstərici null olmamalıdır. Ən aşağı səhifədə hər hansı bir yer ola bilər və bu istisna yaradılacaq.

2150
11 янв. Jan Sunders tərəfindən 11 Yanvarda cavab verildi 2011-01-11 19:52 '11 at 19:52 2011-01-11 19:52

NullReference İstisna - Visual Basic

Visual Basic üçün NullReference Exception C # NullReference Exception . Nəticədə, hər ikisi də istifadə etdikləri .NET Framework'də müəyyən edilən istisnadır. Visual Basic üçün unikal səbəblər nadirdir (bəlkə də yalnız bir).

Bu cavab, Visual Basic sözləri, sözdizimi və kontekstindən istifadə edəcəkdir. Istifadə olunan nümunələr bir çox keçmiş yığma daşqın sualından yaranır. Bu, əlaqələrdən maksimum istifadə etmək, mesajlarda tez-tez rast gəlinən hallardan istifadə etmək üçün edilir. Lazımı olanlar üçün bir az daha izahat verilir. Sizinlə bənzər bir nümunə burada çox ehtimal olunur.

Qeyd:

  1. Bu konsepsiyaya əsaslanır: layihənizdə heç bir kod yoxdur. NullReferenceException (NRE) NullReferenceException , necə tapmaq, onu necə düzəltmək və onu necə NullReferenceException anlamaqda kömək etmək üçün nəzərdə tutulmuşdur. NRE bir çox yollarla baş verə bilər, buna görə də bu sizin yeganə görüşünüz ola bilməz.
  2. Nümunələr (on123.ru yazılarından) həmişə bir şey etmək üçün ən yaxşı yolu göstərmir.
  3. Bir qayda olaraq, ən sadə vasitə istifadə olunur.

İbtidai məna

"Nümunə obyekti olmayan obyekt" mesajı başlanmayan bir obyektdən istifadə etməyə çalışdığınız anlamına gəlir. Aşağıdakılardan birinə gəlir:

  • Ваш код объявлял объектную переменную, но не инициализировал ее (создайте экземпляр или "создайте экземпляр")
  • Что-то, что предполагал ваш код, инициализирует объект, не
  • Возможно, другой код преждевременно аннулировал объект, который все еще используется

Поиск причины

Поскольку проблема - это ссылка на объект, которая является " Nothing , ответ заключается в том, чтобы изучить их, чтобы узнать, какой из них. Затем определите, почему он не инициализирован. Держите мышь над различными переменными, и Visual Studio (VS) покажет их значения - виновником будет Nothing .

2019

285
ответ дан Disaffected 1070452 05 нояб. '14 в 19:08 2014-11-05 19:08

Другим сценарием является приведение нулевого объекта в тип значения . Например, приведенный ниже код:

 object o = null; DateTime d = (DateTime)o; 

Он выкинет NullReferenceException в роли. В приведенном выше примере это кажется совершенно очевидным, но это может произойти в более "поздних связующих" сложных сценариях, где нулевой объект был возвращен из некоторого кода, которого вы не являетесь, и приведение, например, генерируется некоторой автоматической системой.

Одним из примеров этого является этот простой фрагмент привязки ASP.NET с элементом управления календарем:

 <asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" /> 

Здесь SelectedDate на самом деле является свойством типа DateTime типа веб-контроля Calendar , и привязка может отлично вернуть что-то null. Неявный генератор ASP.NET создаст кусок кода, который будет эквивалентен приведенному выше методу. И это вызовет NullReferenceException , которое довольно сложно определить, потому что оно лежит в сгенерированном ASP.NET коде, который компилируется отлично...

219
ответ дан Simon Mourier 28 июня '12 в 15:44 2012-06-28 15:44

Это означает, что рассматриваемая переменная ничем не указана. Я мог бы создать это так:

 SqlConnection connection = null; connection.Open(); 

Это вызовет ошибку, потому что, пока я объявил переменную " connection ", она ничего не указала. Когда я пытаюсь вызвать член " Open ", там нет ссылки для его разрешения, и он выдает ошибку.

Чтобы избежать этой ошибки:

  • Всегда инициализируйте свои объекты, прежде чем пытаться что-либо сделать с ними.
  • Если вы не уверены, является ли объект нулевым, проверьте его с помощью object == null .

Инструмент Resharper JetBrains определит каждое место в вашем коде, которое имеет возможность ошибки нулевой ссылки, позволяя вам установить нулевую проверку. Эта ошибка является источником ошибок номер один, IMHO.

148
ответ дан Chris B. Behrens 11 янв. '11 в 19:52 2011-01-11 19:52

Это означает, что ваш код использовал ссылочную переменную объекта, которая была установлена ​​в значение null (т.е. она не ссылалась на экземпляр фактического объекта).

Чтобы предотвратить ошибку, объекты, которые могут быть пустыми, должны быть проверены на значение null перед использованием.

 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 } 
137
ответ дан Jonathan Wood 11 янв. '11 в 19:52 2011-01-11 19:52

Помните, что независимо от сценария причина всегда одинакова в .NET:

Вы пытаетесь использовать ссылочную переменную, значение которой Nothing / null . Если для ссылочной переменной значение Nothing / null , это означает, что на самом деле оно не содержит ссылку на экземпляр любого объекта, который существует в куче.

Вы либо никогда не присваивали какую-либо переменную, никогда не создавали экземпляр значения, присвоенного переменной, или вы устанавливали переменную равную Nothing / null вручную, или вы вызывали функцию, которая устанавливает переменную в Nothing / null для вас.

92
ответ дан code master 11 янв. '11 в 19:53 2011-01-11 19:53

Примером этого исключения является: Когда вы пытаетесь проверить что-то, это null.

Məsələn:

 string testString = null; //Because it doesn't have a value (ie it null; "Length" cannot do what it needs to do) if (testString.Length == 0) // Throws a nullreferenceexception { //Do something } 

Среда выполнения.NET будет генерировать исключение NullReferenceException при попытке выполнить действие над чем-то, что не было создано, т.е. приведенным выше кодом.

По сравнению с ArgumentNullException, которое обычно выбрасывается как защитная мера, если метод ожидает, что переданное ему значение не является нулевым.

Дополнительная информация содержится в С# NullReferenceException и Null Parameter .

81
ответ дан Alex KeySmith 11 янв. '11 в 19:53 2011-01-11 19:53

Если вы не инициализировали ссылочный тип и хотите установить или прочитать одно из его свойств, он будет генерировать исключение NullReferenceException .

Məsələn:

 Person p = null; p.Name = "Harry"; // NullReferenceException occurs here. 

Вы можете просто избежать этого, проверив, не имеет ли переменная значение null:

 Person p = null; if (p!=null) { p.Name = "Harry"; // Not going to run to this point } 

Чтобы полностью понять, почему выбрано исключение NullReferenceException, важно знать разницу между типами значений и ссылочными типами .

Итак, если вы имеете дело со типами значений , NullReferenceExceptions не может произойти. Хотя вам нужно проявлять бдительность при работе со ссылочными типами !

Только ссылочные типы, как следует из названия, могут содержать ссылки или буквально буквально ничто (или "нуль"). В то время как типы значений всегда содержат значение.

Типы ссылок (эти должны быть проверены):

  • динамический
  • объект
  • строка

Типы значений (вы можете просто игнорировать их):

  • Числовые типы
  • Интегральные типы
  • Типы с плавающей точкой
  • десятичная дробь
  • BOOL
  • Определенные пользователем структуры
76
ответ дан Fabian Bigler 17 мая '13 в 0:40 2013-05-17 00:40

Другим случаем, когда 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) { // ... } 
70
ответ дан Jonathon Reinhart 05 марта '13 в 22:32 2013-03-05 22:32

Вы используете объект, содержащий ссылку нулевого значения. Таким образом, он дает нулевое исключение. В этом примере строковое значение равно null, и при проверке его длины произошло исключение.

Məsələn:

 string value = null; if (value.Length == 0) // <-- Causes exception { Console.WriteLine(value); // <-- Never reached } 

Ошибка исключения:

Необработанное исключение:

System.NullReferenceException: ссылка на объект не установлена ​​в экземпляр объекта. в Program.Main()

61
ответ дан user1814380 10 дек. '12 в 12:59 2012-12-10 12:59

Симон Моурир привел этот пример :

 object o = null; DateTime d = (DateTime)o; // NullReferenceException 

где преобразование (cast) unboxing из object (или из одного из классов System.ValueType или System.Enum или из типа интерфейса) в тип значения (кроме Nullable<> ) само по себе дает NullReferenceException .

В другом направлении преобразование бокса из Nullable<> которое HasValue равно false для ссылочного типа, может дать null ссылку, которая затем может привести к NullReferenceException . Klassik nümunə:

 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<> экземпляров.

50
ответ дан Jeppe Stig Nielsen 10 июля '14 в 18:43 2014-07-10 18:43

В то время как то, что вызывает NullReferenceExceptions и подходы к исключению/исправлению такого исключения, было рассмотрено в других ответах, что многие программисты еще не изучили, как самостоятельно отлаживать такие исключения во время разработки.

В Visual Studio это обычно легко благодаря Visual Studio Debugger .


Во-первых, убедитесь, что правильная ошибка будет обнаружена - см. Как разрешить нарушение "Исключение System.NullReferenceException" в VS2010? Примечание 1

Затем либо " Начать с отладки" (F5), либо " Прикрепить" [отладчик VS] для выполнения процесса . Иногда может быть полезно использовать Debugger.Break , который предложит запустить отладчик.

Теперь, когда выбрано NullReferenceException (или необработанное), отладчик остановится (вспомните правило, установленное выше?) В строке, в которой произошло исключение. Иногда ошибка будет легко заметить.

Например, в следующей строке единственным кодом, который может вызвать исключение, является то, что myString значение null. Это можно проверить, посмотрев окно просмотра или выполнив выражения в окне Immediate .

 var x = myString.Trim(); 

В более сложных случаях, таких как следующее, вам нужно будет использовать один из методов выше (Watch или Immediate Windows), чтобы проверить выражения, чтобы определить, было ли str1 пустым или str2 был нулевым.

 var x = str1.Trim() + str2.Trim(); 

Когда место, где было выбрано исключение, было расположено, оно обычно тривиально по отношению к разуму назад, чтобы выяснить, где введено неверное значение -

Найдите время, необходимое для понимания причины исключения. Проверьте нулевые выражения. Проверьте предыдущие выражения, которые могли бы привести к таким нулевым выражениям. Добавьте точки останова и, по мере необходимости, выполните программу. Используйте отладчик.


1 Если Break on Throws является слишком агрессивным, и отладчик останавливается на NPE в библиотеке.NET или сторонних разработчиков, Break on User-Unhandled может использоваться для ограничения исключений. Кроме того, VS2012 представляет Just My Code, который я рекомендую также включить.

Если вы отлаживаетесь с включенным Just My Code, поведение немного отличается. При включенном Just My Code отладчик игнорирует исключения, связанные с привилегиями обычного языка (CLR), которые выходят за пределы My Code и не проходят через My Code

46
ответ дан user2864740 12 февр. '14 в 22:24 2014-02-12 22:24

Добавление случая, когда имя класса для сущности, используемой в структуре сущности, такое же, как имя класса для файла с кодировкой веб-формы.

Предположим, что у вас есть веб-форма Contact.aspx, чей класс codebehind имеет контакт, и у вас есть контакт с именем организации.

Затем следующий код будет вызывать исключение NullReferenceException при вызове context.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;} } 

Ошибка возникает, когда и класс entity, и codebehind находятся в одном пространстве имен. Чтобы исправить это, переименуйте класс сущности или класс codebehind для Contact.aspx.

Причина Я все еще не уверен в причине. Но всякий раз, когда какой-либо из классов сущностей расширяет System.Web.UI.Page, эта ошибка возникает.

Для обсуждения рассмотрим NullReferenceException в DbContext.saveChanges()

38
ответ дан AbhinavRanjan 18 дек. '13 в 22:31 2013-12-18 22:31

Другой общий случай, когда можно получить это исключение, включает в себя насмешливые классы во время модульного тестирования. Независимо от используемой насмешливой структуры, вы должны убедиться, что все соответствующие уровни иерархии классов должным образом высмеиваются. В частности, все свойства HttpContext , на которые ссылается тестируемый код, должны быть изделены.

См. " Исключение NullReferenceException при проверке пользовательского атрибута AuthorizationAttribute " для несколько подробного примера.

37
ответ дан John Saunders 13 окт. '13 в 5:24 2013-10-13 05:24

У меня есть другая перспектива ответить на это. Такие ответы "что еще можно сделать, чтобы избежать этого? "

При работе в разных слоях , например, в приложении 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(); } } 
36
ответ дан Mukus 07 марта '14 в 2:21 2014-03-07 02:21

В отношении "что мне делать с этим" может быть много @.

Более "формальный" способ предотвращения таких ошибок при разработке применяется дизайн по контракту в вашем коде. Это означает, что вам необходимо установить инварианты классов и/или даже предпосылки и постусловия функций и постусловий в вашей системе при разработке.

Короче говоря, инварианты класса гарантируют, что в вашем классе будут некоторые ограничения, которые не будут нарушены при нормальном использовании (и, следовательно, класс не попадет в несогласованное состояние). Предпосылки означают, что данные, данные как входные данные для функции/метода, должны соответствовать установленным ограничениям и никогда , а постусловия означает, что вывод функции/метода должен снова следовать установленным ограничениям, не нарушая их. Условия контракта должны быть никогда нарушены во время выполнения программы без ошибок, поэтому дизайн по контракту проверяется на практике в режиме отладки, будучи отключенным в версиях, чтобы максимизировать развитую производительность системы.

Таким образом, вы можете избежать случаев NullReferenceException , которые являются результатом нарушения установленных ограничений. Например, если вы используете свойство объекта 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 ); //... } 

По этой причине существует проект Code Contracts для приложений .NET.

В качестве альтернативы, дизайн по контракту может быть применен с помощью утверждений .

ОБНОВЛЕНИЕ: Стоит отметить, что этот термин был придуман Бертраном Мейером в связи с его дизайном языка программирования Эйфеля .

34
ответ дан Nick Louloudakis 26 дек. '14 в 2:54 2014-12-26 02:54

A NullReferenceException возникает, когда мы пытаемся получить доступ к свойствам нулевого объекта или когда значение строки становится пустым и мы пытаемся получить доступ к строковым методам.

Məsələn:

  • При использовании строкового метода пустой строки:

     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 
32
ответ дан Hemant Bavle 18 февр. '14 в 22:12 2014-02-18 22:12

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 

Отладка показала, что модель была Null внутри MyOtherView. Пока я не изменил его на:

 @{ MyEntity M = new MyEntity(); } @Html.Partial("_MyOtherView.cshtml", M); 

И это сработало.

Кроме того, причина, по которой у меня не было Html.Partial , заключалась в том, что Visual Studio иногда генерирует строчные строки с ошибками в 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){ ... } 

Хотя у меня такое чувство, что Visual Studio неправильно интерпретирует амперсанды и скобки.

28
ответ дан Travis Heeter 24 июля '15 в 14:09 2015-07-24 14:09

Что вы можете сделать с этим?

Здесь есть много хороших @, объясняющих, что такое пустая ссылка и как ее отладить. Но очень мало о том, как предотвратить проблему или, по крайней мере, сделать ее легче поймать.

Проверить аргументы

Например, методы могут проверять разные аргументы, чтобы увидеть, являются ли они нулевыми и выбрасывают ArgumentNullException , исключение, явно созданное для этой цели.

Конструктор для ArgumentNullException даже принимает имя параметра и сообщение в качестве аргументов, чтобы вы могли точно сказать разработчику, в чем проблема.

 public void DoSomething(MyObject obj) { if(obj == null) { throw new ArgumentNullException("obj", "Need a reference to obj."); } } 

Использовать инструменты

Есть также несколько библиотек, которые могут помочь. Например, "Resharper" может предоставить вам предупреждения при написании кода, особенно если вы используете их атрибут: 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); } 

Как вы можете видеть выше, как с помощью nullable, вы получите доступ к базовому значению с помощью свойства 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 null . Therefore you only have to check whether address is null`.

Это отличная функция, но она дает вам меньше информации. Это не делает очевидным, какой из 4 является нулевым.

Встроенный как Nullable?

С# имеет красивое сокращение для Nullable<T> , вы можете сделать что-то нулевое, поставив знак вопроса после такого типа int? .

Было бы неплохо, если бы у С# было что-то вроде структуры NotNull<T> выше и имела аналогичную стенографию, может быть, восклицательный знак (!), чтобы вы могли написать что-то вроде: public void WriteName(Person! person) .

20
ответ дан Luis Perez 06 марта '16 в 19:28 2016-03-06 19:28

Исключить исключение NullReferenceException можно с помощью Null-условных операторов в С# 6 и написать меньше кода для обработки нулевых проверок.

Он использовал для проверки значения null перед выполнением операции доступа к члену (?.) или индекса (? [).

Misal

  var name = p?.Spouse?.FirstName; 

эквивалентно:

  if (p != null) { if (p.Spouse != null) { name = p.Spouse.FirstName; } } 

В результате имя будет пустым, если p равно null или p.Spouse - null.

В противном случае имени переменной будет присвоено значение p.Spouse.FirstName.

Для получения дополнительной информации: Нулевые условные операторы

8
ответ дан M.Hassan 30 нояб. '17 в 2:05 2017-11-30 02:05

Интересно, что ни один из @ на этой странице не упоминает два крайних случая, надеюсь, что никто не возражает, если я их добавлю:

Случай с краем # 1: одновременный доступ к словарю

Общие словари в .NET не являются потокобезопасными, и иногда они могут бросать NullReference или даже (чаще) a KeyNotFoundException при попытке получить доступ к ключу из двух параллельных потоков. Исключение в этом случае вводит в заблуждение.

Кромка # 2: небезопасный код

Если a NullReferenceException выбрано кодом unsafe , вы можете посмотреть на переменные указателя и проверить их на IntPtr.Zero или что-то еще. Это одно и то же ( "исключение нулевого указателя" ), но в небезопасном коде переменные часто переводятся в типы значений/массивы и т.д., И вы ударяете головой о стену, задаваясь вопросом, как тип значения может исключение.

(Еще одна причина для небезопасного использования небезопасного кода, если вам это не нужно)

7
ответ дан jazzcat 22 марта '17 в 20:57 2017-03-22 20:57

Строка ошибки "Ссылка на объект не установлена ​​в экземпляр объекта." заявляет, что вы не присвоили экземпляр объекта объектной ссылке, и все же вы получаете доступ к свойствам/методам этого объекта.

например: допустим, что у вас есть класс с именем 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 } } 

выше строка выдает ошибку, потому что ссылка класса myClass объявлена, но не создана, или экземпляр объекта не назначен для referecne этого класса.

Чтобы исправить это, вы должны создать экземпляр (присвоить объект ссылке на этот класс).

 public class Demo { public void testMethod() { myClass ref = null; ref = new myClass(); ref.prop1 = 1; } } 
7
ответ дан Jaimin Dave 08 марта '17 в 13:58 2017-03-08 13:58

Ссылка NullReferenceException или Object, не установленная на экземпляр объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создается. Məsələn:

Предположим, что у вас есть класс с именем Student.

 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 - объявляет только переменную типа Student, обратите внимание, что класс Student не создается в этой точке. Следовательно, когда выполняется инструкция s.GetFullName() , она выкинет исключение NullReferenceException.

2
ответ дан Nick 28 июля '16 в 13:52 2016-07-28 13:52

Ну, простыми словами:

Вы пытаетесь получить доступ к объекту, который не создан или в настоящее время не находится в памяти.

Итак, как решить это:

  • Отладка и отключение отладчика... Это приведет непосредственно к переменной, которая сломана... Теперь ваша задача - просто исправить это. Используя ключевое слово new в соответствующем месте.

  • Если это вызвано некоторыми командами базы данных , потому что объект отсутствует, все, что вам нужно сделать, это выполнить нулевую проверку и обработать его:

     if (i == null) { // Handle this } 
  • Самый сложный... если GC собрал объект уже... Это обычно происходит если вы пытаетесь найти объект, используя строки... То есть, найдя его по имени объекта, может случиться так, что GC уже может его очистить... Это трудно найти и станет проблемой. Лучший способ справиться с этим - делать нулевые проверки там, где это необходимо в процессе разработки. Это сэкономит вам много времени.

Поиск по имени означает, что некоторые фреймворки позволяют использовать FIndObjects с помощью строк, а код может выглядеть так: FindObject ( "ObjectName" );

1
ответ дан Akash Gutha 24 дек. '15 в 10:26 2015-12-24 10:26

Буквально самый простой способ исправить NullReferenceExeption имеет два пути. Если у вас есть GameObject, например, с прикрепленным script и переменной с именем rb (rigidbody), эта переменная начнет пустую, когда вы начнете игру.
Вот почему вы получаете NullReferenceExeption, потому что на компьютере нет данных, хранящихся в этой переменной.

В качестве примера я буду использовать переменную RigidBody.
Мы можем добавить данные действительно легко на самом деле несколькими способами:

  • Добавьте RigidBody к вашему объекту с помощью AddComponent > Физикa > Rigidbody
    Затем зайдите в свой script и введите rb = GetComponent<Rigidbody>();
    Эта строка кода лучше всего работает под вашими функциями Start() или Awake() .
  • Вы можете добавить компонент программно и назначить переменную одновременно с одной строкой кода: rb = AddComponent<RigidBody>();

Дальнейшие примечания. Если вы хотите, чтобы единство добавляло компонент к вашему объекту, и вы, возможно, забыли добавить его, вы можете ввести [RequireComponent(typeof(RigidBody))] над объявлением класса (пробел ниже всех ваших приложений).
Наслаждайтесь и получайте удовольствие от игр!

0
ответ дан CausticLasagne 14 нояб. '17 в 23:17 2017-11-14 23:17

Если мы рассмотрим общие сценарии, в которых может быть выбрано это исключение, доступ к свойствам с объектом вверху.

Məsələn:

 string postalcode=Customer.Address.PostalCode; //if customer or address is null , this will through exeption 

здесь, если адрес равен NULL, тогда вы получите исключение NullReferenceException.

Итак, как практика, мы всегда должны использовать проверку нуля, прежде чем обращаться к свойствам в таких объектах (особенно в родовых)

 string postalcode=Customer?.Address?.PostalCode; //if customer or address is null , this will return null, without through a exception 
0
ответ дан Hiran 24 авг. '17 в 8:55 2017-08-24 08:55

Для типов ссылок по умолчанию используется null , чтобы указать, что они не ссылаются на какой-либо объект. Следовательно, если вы попытаетесь получить доступ к объекту, на который ссылаетесь, и его нет, вы получите NullReferenceException .

Ex üçün:

 SqlConnection connection = null; connection.Open(); 

Когда вы запустите этот код, вы получите:

 System.NullReferenceException: Object reference not set to an instance of an object. 

Вы можете избежать этой ошибки путем кодирования следующим образом:

 if (connection != null){ connection.Open(); } 

Qeyd Чтобы избежать этой ошибки, вы всегда должны инициализировать свои объекты, прежде чем пытаться что-либо сделать с ними.

0
ответ дан Prateek Agrawal 15 нояб. '17 в 23:23 2017-11-15 23:23

Если вы получаете это сообщение во время сохранения или компиляции сборки, просто закройте все файлы, а затем откройте любой файл для компиляции и сохранения.

Для меня причина в том, что я переименовал файл, и старый файл все еще был открыт.

-1
ответ дан Harshal Doshi Jain 14 окт. '17 в 21:48 2017-10-14 21:48

Чтобы использовать методы и член объекта, вам сначала нужно создать этот объект. Если вы его не создали (переменная, которая должна содержать объект, не инициализируется), но вы пытаетесь использовать его методы или переменные, вы получите эту ошибку.

Иногда вы можете просто забыть инициализировать.

Отредактировано: new не может вернуть значение null, но исключение fire при неудаче. Давно это было на некоторых языках, но не больше. Спасибо @John Saunders за указание на это.

-1
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос