Kas yra NullReferenceException Exception ir kaip tai pašalinti?

Turiu kodą ir kai jis įvykdomas, jis išmeta „ NullReferenceException , sakydamas:

Objekto nuoroda nenustatyta objekto atveju.

Ką tai reiškia ir ką galiu padaryti, kad ištaisytumėte šią klaidą?

1878 m
11 янв. John Saunders nustatė sausio 11 d 2011-01-11 19:48 '11, 19:48, 2011-01-11 19:48
@ 34 atsakymai
  • 1
  • 2

Kokia yra priežastis?

Apatinė linija

Bandote naudoti tai, kas yra null (arba Nothing VB.NET). Tai reiškia, kad jūs arba null vertę, arba niekada nenustatėte jo nieko.

Kaip ir visa kita, null aplinkkeliai. Jei „A“ metode jis yra null , gali būti, kad „B“ metodas null „A“.

null gali turėti skirtingas reikšmes:

  1. Objektų kintamieji, kurie yra neišdėstyti ir todėl nieko nenurodo. Tokiu atveju, jei esate NullReferenceException prie tokių objektų savybių ar metodų, tai sukelia „ NullReferenceException .
  2. Kūrėjas sąmoningai naudoja null , nurodydamas, kad nėra reikšmingos vertės. Atkreipkite dėmesį, kad C # kintamiesiems yra netinkamų duomenų tipų (pvz., Duomenų bazių lentelėse gali būti null vertės laukai) - ar galite priskirti juos null kad parodytų, kad jame nėra jokios vertės, pvz., int? a = null; int? a = null; int? a = null; kur klausimų ženklas rodo, kad leidžiama išsaugoti vertę null kintamajame a . Galite tai patikrinti, if (a.HasValue) {...} arba if (a==null) {...} . Pasirinktiniai kintamieji, kaip a šis pavyzdys, leidžia pasiekti vertę per a.Value aiškiai arba kaip įprasta, per a .
    Atkreipkite dėmesį, kad prieiga prie jos per a.Value sukelia InvalidOperationException vietoj NullReferenceException jei a yra null - turite atlikti patikrinimą iš anksto, ty, jei turite kitą kintamąjį su NULL parinktimi int b; tada turėtumėte atlikti tipo užduotis, if (a.HasValue) { b = a.Value; } if (a.HasValue) { b = a.Value; } if (a.HasValue) { b = a.Value; } if (a.HasValue) { b = a.Value; } arba trumpesnis, if (a != null) { b = a; } if (a != null) { b = a; } if (a != null) { b = a; } if (a != null) { b = a; } .

Likusi šio straipsnio dalis išsamiau apibūdina klaidas, kurias dažnai daro daugelis programuotojų, o tai gali sukelti „ NullReferenceException .

Tiksliau

NullReferenceException metimo vykdymo laikas visada reiškia tą patį: bandote naudoti nuorodą, o nuoroda nėra inicijuojama (arba ji buvo kartą inicijuota, bet nebėra inicijuota).

Tai reiškia, kad nuoroda yra null ir jūs negalite pasiekti elementų (pvz., Metodų) per null nuorodą. Paprasčiausias atvejis:

 string foo = null; foo.ToUpper(); 

Tai sukels „ NullReferenceException “ antroje eilutėje, nes negalite skambinti ToUpper() instancijos metodu string nuorodoje, nukreipiančioje į null .

derinimo

Kaip rasti „ NullReferenceException šaltinį? Be to, kad išnagrinėtų pačią išimtį, kuri bus išmesta tiksliai ten, kur ji atsiranda, „Visual Studio“ taikomos bendrosios derinimo taisyklės: įdėkite strateginius taškinius taškus ir patikrinkite savo kintamuosius , pakreipdami virš jų vardų, atidarę (Greito) peržiūros >

Jei norite sužinoti, kur yra arba nėra įdiegta nuoroda, dešiniuoju pelės mygtuku spustelėkite jo pavadinimą ir pasirinkite „Rasti visas nuorodas“. Tada kiekvienoje rastoje vietoje galite įterpti pertraukos tašką ir paleisti programą su pridedamu derintuvu. Kiekvieną kartą, kai debugeris įeina į tokį pertraukos tašką, reikia nustatyti, ar norite, kad nuoroda būtų ne nulinė, patikrinkite kintamąjį ir įsitikinkite, kad jis nurodo pavyzdį, kai tikitės.

Taigi, po programos srauto, galite rasti vietą, kurioje egzempliorius neturėtų būti lygus nuliui, ir kodėl jis įdiegtas neteisingai.

Pavyzdžiai

Kai kurie bendri scenarijai, kuriuose gali būti pasirinkta išimtis:

įprasta

 ref1.ref2.ref3.member 

Jei ref1 arba ref2 arba ref3 yra null, gausite „ NullReferenceException . Jei norite išspręsti problemą, išsiaiškinkite, kuris iš jų yra nulis, perrašydami išraišką į paprastesnį ekvivalentą:

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

Visų pirma, „ HttpContext.Current.User.Identity.Name , „ HttpContext.Current gali būti nulinis arba User nuosavybė gali būti nulinė arba „ Identity nuosavybė gali būti nulinė.

netiesioginis

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

Jei norite išvengti nuorodos į „Null“ (Asmuo), galite jį inicijuoti patronuojančios (knygos) objekto konstruktoriuje.

Įdėtų objektų iniciatoriai

Tas pats pasakytina ir apie įdėtų objektų iniciatorius:

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

Jis verčia

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

Kol naudojamas new raktinis žodis, jis sukuria tik naują „ Book egzempliorių, bet ne naują „ Person egzempliorių, todėl Author ypatybė vis dar yra null .

Įdėtos kolekcijos iniciatoriai

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

Įdėtų kolekcijų iniciatoriai elgiasi taip:

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

Jis verčia

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

new Person sukuria tik asmens egzempliorių, tačiau Books rinkinys vis dar yra null . Kolekcijos p1.Books sintaksė nesukuria „ p1.Books kolekcijos, ji verčia tik į p1.Books.Add(...) .

masyvas

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

Array elementai

 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. 

Kietosios matricos

 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. 

Kolekcija / sąrašas / žodynas

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

Diapazono kintamasis (netiesioginis / atidėtas)

 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. 

Renginiai

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

Netinkamos pavadinimo sutartys:

Jei laukus pavadinote skirtingai nei vietiniai, galbūt supratote, kad niekada nepavyko inicijuoti šio lauko.

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

Tai galima išspręsti užpildant prefikso lauko sutartį su pabraukimu:

 private Customer _customer; 

ASP.NET puslapio gyvavimo ciklas:

 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 sesijos vertės

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

Tuščias ASP.NET MVC žiūrovas

Jei išimtis, susijusi su „ @Model nuosavybe, atsitinka „ASP.NET MVC“ vaizde, turite suprasti, kad Model gauna veiksmo metodo vertę, kai rodomas return vaizdas. Kai grąžinate tuščią modelį (arba modelio savybę) iš savo valdiklio, išimtis atsiranda tada, kai peržiūros metu pasiekiama:

 // 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 kontrolės ir įvykių kūrimo tvarka

WPF kontrolė sukuriama per pokalbį į „ InitializeComponent “ tokia tvarka, kuria jie rodomi vaizdiniame medyje. NullReferenceException bus iškeltas pradžioje sukurtų valdiklių su įvykių tvarkytojais atveju, ir tt NullReferenceException atleistas per „ InitializeComponent kuris nurodo vėlai sukurtus valdiklius.

Pavyzdžiui:

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

Čia comboBox1 sukuriamas prieš label1 . Jei comboBox1_SelectionChanged bando kreiptis į „label1, jis dar nebuvo sukurtas.

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

Deklaracijų eilės keitimas XAML (t. Y. comboBox1 prieš comboBox1 , ignoruojant dizaino filosofijos problemas, bent jau čia NullReferenceException leidžiama „ NullReferenceException .

Vaidino, as

 var myThing = someObject as Thing; 

Tai nepadidina „InvalidCastException“, bet grąžina null jei nepavyksta paleisti (ir kai kai pats objektas yra nulis). Taigi turėkite tai omenyje.

LINQ FirstOrDefault () ir SingleOrDefault ()

Paprastos „ First() ir „ Single() versijos išskiria išimtis, kai nėra nieko. Tokiu atveju „OrDefault“ versijos grąžina null. Taigi turėkite tai omenyje.

už kiekvieną

foreach mesti, kai bando kartoti nulinę kolekciją. Paprastai sukelia netikėtas null rezultatų, grįžtančių iš kolekcijų, rezultatas.

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

Realesnis pavyzdys yra mazgų parinkimas iš XML dokumento. Bus aptikta, jei nerasite mazgų, bet pradinis derinimas rodo, kad visos savybės yra tinkamos:

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

Vengimo būdai

Aiškiai tikrinant null vertę ir ignoruojant nulį.

Jei tikitės, kad nuoroda kartais būna tuščia, prieš naudodamiesi instancijos nariais, galite patikrinti, ar ši nuoroda yra tuščia:

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

Aiškiai patikrinkite null vertę ir nurodykite numatytąją vertę.

Metodai, kuriais raginama tikėtis, kad egzempliorius grįš, gali grįžti į null , pavyzdžiui, kai ieškomo objekto nerandate. Jei taip yra, galite pasirinkti numatytąją vertę:

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

Aš aiškiai null vertės null metodą ir nustatau savo išimtį.

Taip pat galite sukurti priskirtą išimtį, tik norėdami ją užfiksuoti skambinimo kode:

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

Naudokite Debug.Assert jei reikšmė niekada neturėtų būti Debug.Assert kad problema būtų sugauta prieš Debug.Assert išimtį.

Kai žinote, kad kūrimo metu šis metodas gali būti, bet niekada negrąžinamas, galite naudoti Debug.Assert() kad kuo greičiau Debug.Assert() kai tai įvyksta:

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

Nors šis patikrinimas nesibaigs jūsų išleidimo versijoje , priverčia jį iš naujo nustatyti „ NullReferenceException , kai book == null vykdymo metu išleidimo režime.

Naudokite „ GetValueOrDefault() reikšmių tipams, kurių vertė yra null kad būtų nustatyta numatytoji vertė, kai ji yra null .

 DateTime? appointment = null; Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Will display the default value provided (DateTime.Now), because appointment is null. appointment = new DateTime(2022, 10, 20); Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Will display the appointment date, not the default 

Naudokite nulinį koalicijos operatorių: ?? [С #] arba If() [VB].

Sumažinti iki numatytojo, kai susiduriama su 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; } 

Naudokite nulinės būsenos operatorių: ?. arba ?[x] matricoms (galima rasti C # 6 ir VB.NET 14):

Kartais tai vadinama saugia navigacija arba „Elvis“ (po jos formos). Jei išraiška kairėje pusėje pareiškimas yra NULL, tada dešinėje pusėje nebus įvertintas, ir nulis bus grąžintas vietoj. Tai reiškia tokius atvejus:

 var title = person.Title.ToUpper(); 

Jei asmuo neturi vardo, tai iškils išimtis, nes ji bando skambinti „ ToUpper už nulinės vertės turtą.

C # 5 ir žemiau tai galima apsaugoti:

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

Dabar pavadinimo kintamasis bus nulis, o ne išimties išimtis. C # 6 sukuria trumpesnę sintaksę:

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

Dėl to kintamojo pavadinimas bus null , o skambutis į „ ToUpper nevykdomas, jei person.Title yra null .

Žinoma, vis tiek reikia patikrinti nulinio title arba naudoti nulinės būklės operatorių kartu su nulinio sutapimo operatoriumi ( ?? ), kad nustatytumėte numatytąją vertę:

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

Taip pat matricų atveju galite naudoti ?[i] taip:

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

Tai bus daroma taip: Jei myIntArray yra nulinis, išraiška grąžina null ir jūs galite saugiai jį patikrinti. Jei jame yra masyvas, jis atliks tą patį kaip: elem = myIntArray[i]; ir grąžina i -tą elementą.

Specialūs metodai derinti ir nustatyti nulinio poslinkio iteratoriuose metodus

C # palaiko „iteratorių blokus“ (vadinamus „generatoriais“ kai kuriose kitose populiariose kalbose). Išimčių išimčių išimtys gali būti ypač sudėtingos derinant iteratoriaus blokus dėl atidėto vykdymo:

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

Jei whatever , null MakeFrob whatever rezultatai yra null , „ MakeFrob “ mesti. Dabar galite manyti, kad tai yra teisingas dalykas:

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

Kodėl tai negerai? Kadangi iteratoriaus blokas iš tikrųjų neprasideda tol, kol jis nebus foreach ! Skambinimas „ GetFrobs paprasčiausiai grąžina objektą, kuris kartojant pradės iteratoriaus bloką.

Rašydami nulinį patikrinimą, venkite nulinio dereferencijos, bet nulinio argumento išimtį perkelsite į iteracijos tašką, o ne į skambučio tašką, ir tai labai paini, kad derintumėte.

Teisingas pataisymas:

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

Tai reiškia, kad sukurkite privatų pagalbininko metodą, turintį iteratoriaus bloko logiką, ir atviro paviršiaus metodą, kuris atlieka nulinį patikrinimą ir grąžina iteratorių. Dabar, „ GetFrobs , iš karto atliekamas nulinis patikrinimas, o tada „ GetFrobsForReal “ įvykdomas, kai seka kartojasi.

Jei peržiūrėsite LINQ nuorodos šaltinį objektams, pamatysite, kad šis metodas naudojamas visur. Tai yra šiek tiek sunkiau rašyti, tačiau jis palengvina klaidų derinimą su klaidomis. Optimizuokite savo kodą skambintojo patogumui, o ne autoriaus patogumui .

Pastaba dėl nesaugių nesaugių kodų skirtumų

„C #“ yra „nesaugus“ režimas, kuris, kaip rodo pavadinimas, yra labai pavojingas, nes nėra taikomi įprastiniai saugumo mechanizmai, užtikrinantys saugumą ir tipo saugą. Jei neturite gilaus supratimo apie tai, kaip veikia atmintis, neturėtumėte rašyti nesaugaus kodo .

Nesaugiu režimu turėtumėte žinoti du svarbius faktus:

  • Nulinio rodyklės nukreipimas sukelia tą pačią išimtį kaip ir nulinės atskaitos nustatymas
  • Neteisingo ne nulinio rodiklio nukreipimas gali sukelti šią išimtį tam tikromis aplinkybėmis

Norėdami suprasti, kodėl taip yra, tai padeda suprasti, kaip .NET pirmiausia sukuria nulinių skirtumų išimtis. (Ši informacija taikoma „.NET“, veikiančiai „Windows“; kitose operacinėse sistemose naudojami panašūs mechanizmai.)

Atmintis virtualizuojama sistemoje „Windows“; Kiekvienas procesas įgyja virtualiosios atminties erdvę iš daugelio atminties „puslapių“, kuriuos stebi operacinė sistema. Kiekviename atminties puslapyje nustatomos vėliavos, kurios nustato, kaip jos naudojamos: skaityti, rašyti, vykdyti ir tt Žemiausias puslapis pažymėtas kaip „duoti klaidą, jei jis kada nors naudojamas“.

Tiek nulinis žymeklis, tiek nulinė nuoroda C # yra viduje pateikiami kaip skaitinė nulio reikšmė, todėl bet koks bandymas jį pašalinti atitinkamoje atminties atmintyje lemia tai, kad operacinė sistema sukuria klaidą. Tada „.NET“ vykdymo trukmė aptinka šią klaidą ir paverčia ją nulinės išimtimi.

Tas faktas, kad nulinio rodiklio ir nulinės nuorodos atskyrimas sukuria tą pačią išimtį.

Kaip apie antrąjį elementą? Paskirstant bet kokį neteisingą rodiklį, kuris pasiekia žemiausią virtualiosios atminties puslapį, atsiranda ta pati operacinės sistemos klaida ir ta pati išimtis.

Kodėl tai prasminga? Na, tarkime, kad turime struktūrą, kurioje yra du intai, ir nevaldomas rodiklis yra nulis. Jei stengiamės išskirti antrąją int struktūrą, CLR nesistengs pasiekti prieigos prie nulinės vietos; jis gaus prieigą prie saugyklos ketvirtoje vietoje. Bet logiškai tai yra nulinis dereference, nes mes gauname šį adresą per nulį.

Jei dirbate su nesaugiu kodu, ir jūs gaunate išimtį naudodami išskirtinę išimtį, tiesiog nepamirškite, kad įsibrovėlio rodyklė neturėtų būti nulinė. Tai gali būti bet kuri žemiausio puslapio vieta, ir ši išimtis bus sukurta.

2150
11 янв. John Saunders atsakymas dėl sausio 11 d 2011-01-11 19:52 '11, 19:52, 2011-01-11 19:52

NullReference išimtis - „Visual Basic“

NullReference ExceptionVisual Basic“ NullReference Exception skiriasi nuo „ NullReference ExceptionC #“ . Galų gale jie abu praneša apie tą pačią išimtį, apibrėžtą .NET Framework, kurią jie abu naudoja. Visual Basic unikalios priežastys yra retos (galbūt tik viena).

Šiame atsakyme bus naudojami „Visual Basic“ terminai, sintaksė ir kontekstas. Naudojami pavyzdžiai kilę iš daugelio praeities stekų perpildymo klausimų. Tai daroma norint maksimaliai padidinti svarbą, naudojant situacijas, kurios dažnai randamos pranešimuose. Taip pat pateikiama šiek tiek daugiau paaiškinimų tiems, kuriems gali prireikti. Pvz.

Pastaba:

  1. Tai grindžiama koncepcija: nėra kodo įterpti į jūsų projektą. Ji sukurta taip, kad padėtų jums suprasti, kas sukelia „ NullReferenceException (NRE), kaip ją rasti, kaip ją išspręsti ir kaip ją išvengti. NRE gali būti suaktyvinta daugeliu būdų, todėl mažai tikėtina, kad tai bus tik jūsų susitikimas.
  2. Pavyzdžiai (iš „ngn-wiki.ru“ pranešimų) ne visada rodo geriausią būdą ką nors padaryti.
  3. Paprastai naudojama paprasčiausia priemonė.

Pirminė reikšmė

Pranešimas „Objektas nėra nustatytas į objekto pavyzdį“ reiškia, kad bandote naudoti ne inicijuotą objektą. Jis patenka į vieną iš šių veiksmų:

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

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

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

Вы также должны удалить блоки Try/Catch из соответствующего кода, особенно те, где в блоке Catch ничего нет. Это приведет к сбою вашего кода при попытке использовать объект Nothing . Это то, что вы хотите, потому что оно идентифицирует точное местоположение проблемы и позволяет идентифицировать вызывающий объект.

MsgBox в Catch, который отображает Error while... , мало поможет. Этот метод также приводит к очень плохим вопросам, потому что вы не можете описать фактическое исключение, объект или даже строку кода, где это происходит.

Вы также можете использовать Locals Window ( Debug → Windows → Locals ) для проверки ваших объектов.