Pengunjung yang akan datang, jawaban atas pertanyaan ini juga berlaku untuk ArgumentNullException . Jika pertanyaan Anda telah ditutup sebagai duplikat dari pertanyaan ini, dan Anda mengalami ANE, harap ikuti petunjuk di jawaban untuk debug dan perbaiki masalah Anda.
@will ANE seharusnya hanya terjadi jika null dilewatkan sebagai parameter. Bisakah Anda memberi contoh jika pertanyaan ANE ditutup sebagai duplikat dari pertanyaan ini?
John Saunders
Itu muncul di Meta, tetapi saya harus menggali tautannya. Tetapi untuk komentar itu, ANE hanyalah sebuah NRE tetapi seseorang menambahkan cek preemptive, dan Anda setidaknya tahu persis apa yang null (nama argumen diberikan), jadi sedikit lebih mudah untuk mendiagnosis daripada NRE yang lurus.
Jawaban:
2416
Apa penyebabnya?
Intinya
Anda mencoba menggunakan sesuatu yang ada null(atau Nothingdi VB.NET). Ini berarti Anda mengaturnya null, atau Anda tidak pernah mengaturnya sama sekali.
Seperti yang lainnya, nullakan diedarkan. Jika nulldalam metode "A", bisa jadi metode "B" meneruskan nullke metode "A".
null dapat memiliki arti yang berbeda:
Variabel objek yang tidak diinisialisasi dan karenanya tidak menunjukkan apa-apa. Dalam hal ini, jika Anda mengakses properti atau metode objek seperti itu, itu menyebabkan a NullReferenceException.
Pengembang menggunakan nullsengaja untuk menunjukkan tidak ada nilai berarti yang tersedia. Perhatikan bahwa C # memiliki konsep datatypes nullable untuk variabel (seperti tabel database dapat memiliki bidang nullable) - Anda dapat menetapkannya nulluntuk menunjukkan tidak ada nilai yang tersimpan di dalamnya, misalnya di int? a = null;mana tanda tanya menunjukkan bahwa diperbolehkan menyimpan nol dalam variabel a. Anda dapat memeriksa apakah dengan if (a.HasValue) {...}atau dengan if (a==null) {...}. Variabel nullable, seperti acontoh ini, memungkinkan untuk mengakses nilai melalui a.Valuesecara eksplisit, atau sama seperti normal via a. Perhatikan bahwa mengaksesnya melalui a.Valuemelempar InvalidOperationExceptionbukan NullReferenceExceptionjika aitunull- Anda harus melakukan pemeriksaan sebelumnya, yaitu jika Anda memiliki variabel on-nullable lain int b;maka Anda harus melakukan tugas seperti if (a.HasValue) { b = a.Value; }atau lebih pendek if (a != null) { b = a; }.
Sisa dari artikel ini membahas lebih detail dan menunjukkan kesalahan yang sering dilakukan oleh banyak programmer yang dapat menyebabkan a NullReferenceException.
Lebih spesifik
The runtimemelemparkan NullReferenceExceptionselalu berarti hal yang sama: Anda mencoba untuk menggunakan referensi, dan referensi tidak diinisialisasi (atau itu sekali diinisialisasi, tetapi tidak lagi diinisialisasi).
Ini artinya rujukannya null, dan Anda tidak dapat mengakses anggota (seperti metode) melalui nullrujukan. Kasus paling sederhana:
string foo =null;
foo.ToUpper();
Ini akan melempar NullReferenceExceptionpada baris kedua karena Anda tidak dapat memanggil metode instance ToUpper()pada stringreferensi yang menunjuk null.
Debugging
Bagaimana Anda menemukan sumber NullReferenceException? Selain melihat pengecualian itu sendiri, yang akan dilemparkan tepat di lokasi di mana itu terjadi, aturan umum debugging di Visual Studio berlaku: tempatkan breakpoint strategis dan periksa variabel Anda , baik dengan mengarahkan mouse di atas nama mereka, membuka ( Cepat) Tonton jendela atau gunakan berbagai panel debug seperti Lokal dan Autos.
Jika Anda ingin mengetahui di mana referensi itu diatur atau tidak, klik kanan namanya dan pilih "Temukan Semua Referensi". Anda kemudian dapat menempatkan breakpoint di setiap lokasi yang ditemukan dan menjalankan program Anda dengan debugger terpasang. Setiap kali debugger memecah breakpoint seperti itu, Anda perlu menentukan apakah Anda mengharapkan referensi tidak nol, memeriksa variabel, dan memverifikasi bahwa itu menunjuk ke sebuah instance ketika Anda mengharapkannya.
Dengan mengikuti alur program dengan cara ini, Anda dapat menemukan lokasi di mana instance tidak boleh null, dan mengapa tidak diatur dengan benar.
Contohnya
Beberapa skenario umum di mana pengecualian dapat dilemparkan:
Umum
ref1.ref2.ref3.member
Jika ref1 atau ref2 atau ref3 adalah nol, maka Anda akan mendapatkan NullReferenceException. Jika Anda ingin menyelesaikan masalah, maka cari tahu yang mana yang nol dengan menulis ulang ekspresi yang sederhananya:
Secara khusus, dalam HttpContext.Current.User.Identity.Name, HttpContext.Currentbisa jadi nol, atau Userproperti bisa nol, atau Identityproperti bisa nol.
Tidak langsung
publicclassPerson{publicintAge{get;set;}}publicclassBook{publicPersonAuthor{get;set;}}publicclassExample{publicvoidFoo(){Book b1 =newBook();int authorAge = b1.Author.Age;// You never initialized the Author property.// there is no Person to get an Age from.}}
Jika Anda ingin menghindari referensi nol anak (Orang), Anda bisa menginisialisasi dalam konstruktor objek orangtua (Buku).
Inisialisasi Objek Bersarang
Hal yang sama berlaku untuk inisialisasi objek bersarang:
Book b1 =newBook{Author={Age=45}};
Ini diterjemahkan menjadi
Book b1 =newBook();
b1.Author.Age=45;
Sementara newkata kunci digunakan, itu hanya membuat contoh baru Book, tetapi bukan contoh baru Person, sehingga Authorproperti tetap null.
Person p1 =newPerson{Books={newBook{Title="Title1"},newBook{Title="Title2"},}};
Ini diterjemahkan menjadi
Person p1 =newPerson();
p1.Books.Add(newBook{Title="Title1"});
p1.Books.Add(newBook{Title="Title2"});
Satu- new Personsatunya yang membuat instance Person, tetapi Bookskoleksinya tetap null. InitializerSintaks koleksi tidak untuk membuat koleksi p1.Books, itu hanya menerjemahkan ke p1.Books.Add(...)pernyataan.
Himpunan
int[] numbers =null;int n = numbers[0];// numbers is null. There is no array to index.
Elemen Array
Person[] people =newPerson[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.
Array bergerigi
long[][] array =newlong[1][];
array[0][0]=3;// is null because only the first dimension is yet initialized.// Use array[0] = new long[2]; first.
Koleksi / Daftar / Kamus
Dictionary<string,int> agesForNames =null;int age = agesForNames["Bob"];// agesForNames is null.// There is no Dictionary to perform the lookup.
Variabel Rentang (Tidak Langsung / Ditangguhkan)
publicclassPerson{publicstringName{get;set;}}var people =newList<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.
Acara
publicclassDemo{publiceventEventHandlerStateChanged;protectedvirtualvoidOnStateChanged(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.
Ini dapat dipecahkan dengan mengikuti konvensi ke bidang awalan dengan garis bawah:
privateCustomer _customer;
ASP.NET Page Life cycle:
publicpartialclassIssues_Edit:System.Web.UI.Page{protectedTestIssue myIssue;protectedvoidPage_Load(object sender,EventArgs e){if(!IsPostBack){// Only called on first load, not when button clicked
myIssue =newTestIssue();}}protectedvoidSaveButton_Click(object sender,EventArgs e){
myIssue.Entry="NullReferenceException here!";}}
Nilai Sesi ASP.NET
// if the "FirstName" session value has not yet been set,// then this line will throw a NullReferenceExceptionstring firstName =Session["FirstName"].ToString();
ASP.NET MVC model tampilan kosong
Jika pengecualian terjadi ketika mereferensikan properti @Modeldalam ASP.NET MVC View, Anda perlu memahami bahwa Modelakan diatur dalam metode tindakan Anda, saat Anda returnmelihatnya. Saat Anda mengembalikan model kosong (atau properti model) dari controller Anda, pengecualian terjadi ketika pandangan mengaksesnya:
// ControllerpublicclassRestaurant:Controller{publicActionResultSearch(){returnView();// Forgot the provide a Model here.}}// Razor view @foreach(var restaurantSearch inModel.RestaurantSearch)// Throws.{}<p>@Model.somePropertyName</p><!--Alsothrows-->
Perintah dan Acara Pembuatan Kontrol WPF
WPFkontrol dibuat selama panggilan ke InitializeComponentdalam urutan mereka muncul di pohon visual. A NullReferenceExceptionakan dimunculkan dalam kasus kontrol yang dibuat lebih awal dengan pengendali event, dll., Yang terbakar selama InitializeComponentreferensi yang membuat kontrol yang dibuat terlambat.
Sebagai contoh :
<Grid><!-- Combobox declared first --><ComboBoxName="comboBox1"Margin="10"SelectedIndex="0"SelectionChanged="comboBox1_SelectionChanged"><ComboBoxItemContent="Item 1"/><ComboBoxItemContent="Item 2"/><ComboBoxItemContent="Item 3"/></ComboBox><!-- Label declared later --><LabelName="label1"Content="Label"Margin="10"/></Grid>
Di sini comboBox1dibuat sebelumnya label1. Jika comboBox1_SelectionChangedupaya untuk mereferensikan `label1, itu belum akan dibuat.
Mengubah urutan deklarasi dalam XAML(yaitu, daftar label1sebelumnya comboBox1, mengabaikan masalah filosofi desain, setidaknya akan menyelesaikan di NullReferenceExceptionsini.
Dipadukan dengan as
var myThing = someObject asThing;
Ini tidak melempar InvalidCastExceptiontetapi mengembalikan a nullketika para pemain gagal (dan kapan someObjectitu sendiri nol). Jadi sadarilah itu.
LINQ FirstOrDefault()danSingleOrDefault()
Versi polos First()dan Single()melempar pengecualian ketika tidak ada. Versi "OrDefault" mengembalikan null dalam kasus itu. Jadi sadarilah itu.
untuk setiap
foreachmelempar ketika Anda mencoba untuk mengembalikan koleksi nol. Biasanya disebabkan oleh nullhasil tak terduga dari metode yang mengembalikan koleksi.
List<int> list =null;foreach(var v in list){}// exception
Contoh yang lebih realistis - pilih node dari dokumen XML. Akan melempar jika node tidak ditemukan tetapi debugging awal menunjukkan bahwa semua properti valid:
foreach(var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))
Cara untuk Dihindari
Secara eksplisit memeriksa nulldan mengabaikan nilai nol.
Jika Anda mengharapkan referensi kadang menjadi nol, Anda dapat memeriksanya nullsebelum mengakses anggota instance:
Periksa secara eksplisit nulldan berikan nilai default.
Metode memanggil Anda berharap untuk kembali contoh dapat kembali null, misalnya ketika objek yang dicari tidak dapat ditemukan. Anda dapat memilih untuk mengembalikan nilai default saat ini:
Periksa secara eksplisit nulldari panggilan metode dan berikan pengecualian khusus.
Anda juga dapat melempar pengecualian khusus, hanya untuk menangkapnya dalam kode panggilan:
stringGetCategory(string bookTitle){var book = library.FindBook(bookTitle);// This may return nullif(book ==null)thrownewBookNotFoundException(bookTitle);// Your custom exceptionreturn book.Category;}
Gunakan Debug.Assertjika suatu nilai tidak boleh null, untuk menangkap masalah lebih awal dari pengecualian terjadi.
Ketika Anda tahu selama pengembangan bahwa suatu metode mungkin bisa, tetapi tidak harus kembali null, Anda dapat menggunakannya Debug.Assert()untuk memecahkan sesegera mungkin ketika itu terjadi:
stringGetTitle(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 codereturn book.Title;// Will never throw NullReferenceException in Debug mode.}
Meskipun pemeriksaan ini tidak akan berakhir di build rilis Anda , menyebabkannya untuk membuang NullReferenceExceptionlagi ketika book == nullsaat runtime dalam mode rilis.
Gunakan GetValueOrDefault()untuk nullabletipe nilai untuk memberikan nilai default saat itu null.
DateTime? appointment =null;Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));// Will display the default value provided (DateTime.Now), because appointment is null.
appointment =newDateTime(2022,10,20);Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));// Will display the appointment date, not the default
Gunakan operator penggabungan nol: ??[C #] atau If()[VB].
Singkatan untuk memberikan nilai default ketika nullditemui:
IServiceCreateService(ILogger log,Int32? frobPowerLevel){var serviceImpl =newMyService(log ??NullLog.Instance);// Note that the above "GetValueOrDefault()" can also be rewritten to use// the coalesce operator:
serviceImpl.FrobPowerLevel= frobPowerLevel ??5;}
Gunakan operator kondisi nol: ?.atau ?[x]untuk array (tersedia dalam C # 6 dan VB.NET 14):
Ini juga kadang-kadang disebut operator navigasi aman atau Elvis (setelah bentuknya). Jika ekspresi di sisi kiri operator adalah nol, maka sisi kanan tidak akan dievaluasi, dan sebaliknya dikembalikan. Itu artinya kasus-kasus seperti ini:
var title = person.Title.ToUpper();
Jika orang tersebut tidak memiliki judul, ini akan menimbulkan pengecualian karena ia mencoba untuk memanggil ToUpperproperti dengan nilai nol.
Di dalam C# 5dan di bawah, ini dapat dijaga dengan:
var title = person.Title==null?null: person.Title.ToUpper();
Sekarang variabel judul akan menjadi nol alih-alih melemparkan pengecualian. C # 6 memperkenalkan sintaks yang lebih pendek untuk ini:
var title = person.Title?.ToUpper();
Ini akan menghasilkan variabel judul menjadi null, dan panggilan ke ToUppertidak dilakukan jika person.Titleada null.
Tentu saja, Anda masih harus memeriksa titlenol atau menggunakan operator kondisi nol bersama dengan operator penggabungan nol ( ??) untuk memberikan nilai default:
// regular null checkint titleLength =0;if(title !=null)
titleLength = title.Length;// If title is null, this would throw NullReferenceException// combining the `?` and the `??` operatorint titleLength = title?.Length??0;
Demikian juga, untuk array Anda dapat menggunakan ?[i]sebagai berikut:
Ini akan melakukan hal berikut: Jika myIntArraybernilai nol, ekspresi mengembalikan nol dan Anda dapat memeriksanya dengan aman. Jika mengandung array, ia akan melakukan hal yang sama seperti:
elem = myIntArray[i];dan mengembalikan i<sup>th</sup>elemen.
Gunakan konteks nol (tersedia dalam C # 8):
Diperkenalkan di C# 8sana konteks nol dan jenis referensi nullable melakukan analisis statis pada variabel dan memberikan peringatan kompilator jika nilai berpotensi nol atau telah diatur ke nol. Jenis referensi yang dapat dibatalkan memungkinkan jenis untuk secara eksplisit diizinkan menjadi nol.
Konteks anotasi yang dapat dibatalkan dan konteks peringatan yang dapat dibatalkan dapat diatur untuk proyek menggunakan Nullableelemen dalam csprojfile Anda . Elemen ini mengonfigurasikan bagaimana kompiler menafsirkan nullability tipe dan peringatan apa yang dihasilkan. Pengaturan yang valid adalah:
aktifkan: Konteks anotasi yang dapat dibatalkan diaktifkan. Konteks peringatan nullable diaktifkan. Variabel dari tipe referensi, string misalnya, tidak dapat dibatalkan. Semua peringatan nullability diaktifkan.
disable: Konteks penjelasan nullable dinonaktifkan. Konteks peringatan nullable dinonaktifkan. Variabel tipe referensi tidak diketahui, sama seperti versi C # sebelumnya. Semua peringatan nullability dinonaktifkan.
safeonly: Konteks anotasi yang dapat dibatalkan diaktifkan. Konteks peringatan yang dapat dibatalkan hanya aman. Variabel tipe referensi tidak dapat dibatalkan. Semua peringatan nullability keselamatan diaktifkan.
peringatan: Konteks anotasi yang dapat dibatalkan dinonaktifkan. Konteks peringatan nullable diaktifkan. Variabel tipe referensi tidak diperhatikan. Semua peringatan nullability diaktifkan.
safeonlywarnings: Konteks anotasi yang dapat dibatalkan dinonaktifkan. Konteks peringatan yang dapat dibatalkan hanya aman. Variabel tipe referensi tidak diperhatikan. Semua peringatan nullability keselamatan diaktifkan.
Tipe referensi nullable dicatat menggunakan sintaksis yang sama dengan tipe nilai nullable: a ?ditambahkan ke tipe variabel.
Teknik khusus untuk debugging dan memperbaiki null deref di iterators
C#mendukung "blok iterator" (disebut "generator" dalam beberapa bahasa populer lainnya). Pengecualian null dereference bisa sangat sulit untuk debug di blok iterator karena eksekusi yang ditangguhkan:
publicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}...FrobFactory factory = whatever;IEnumerable<Frobs> frobs =GetFrobs();...foreach(Frob frob in frobs){...}
Jika whateverhasilnya nullmaka MakeFrobakan melempar. Sekarang, Anda mungkin berpikir bahwa hal yang benar untuk dilakukan adalah ini:
// DON'T DO THISpublicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){if(f ==null)thrownewArgumentNullException("f","factory must not be null");for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}
Kenapa ini salah? Karena blok iterator tidak benar - benar berjalan sampai foreach! Panggilan untuk GetFrobshanya mengembalikan objek yang ketika iterasi akan menjalankan blok iterator.
Dengan menulis cek nol seperti ini, Anda mencegah null dereference, tetapi Anda memindahkan pengecualian argumen nol ke titik iterasi , bukan ke titik panggilan , dan itu sangat membingungkan untuk debug .
Perbaikan yang benar adalah:
// DO THISpublicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){// No yields in a public method that throws!if(f ==null)thrownewArgumentNullException("f","factory must not be null");returnGetFrobsForReal(f, count);}privateIEnumerable<Frob>GetFrobsForReal(FrobFactory f,int count){// Yields in a private methodDebug.Assert(f !=null);for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}
Yaitu, buat metode pembantu pribadi yang memiliki logika blok iterator, dan metode permukaan publik yang melakukan pemeriksaan nol dan mengembalikan iterator. Sekarang ketika GetFrobsdipanggil, pemeriksaan nol terjadi segera, dan kemudian GetFrobsForRealdijalankan ketika urutan diulang.
Jika Anda memeriksa sumber referensi untuk LINQObjek, Anda akan melihat bahwa teknik ini digunakan di seluruh. Menulisnya sedikit lebih kikuk, tetapi itu membuat kesalahan nullging debugging jauh lebih mudah. Optimalkan kode Anda untuk kenyamanan penelepon, bukan kenyamanan penulis .
Catatan tentang null dereferences in dalam kode tidak aman
C#memiliki mode "tidak aman" yang, seperti namanya, sangat berbahaya karena mekanisme keselamatan normal yang memberikan keamanan memori dan keamanan tipe tidak ditegakkan. Anda tidak boleh menulis kode yang tidak aman kecuali jika Anda memiliki pemahaman yang mendalam dan mendalam tentang cara kerja memori .
Dalam mode tidak aman, Anda harus mengetahui dua fakta penting:
dereferencing sebuah null pointer menghasilkan pengecualian yang sama seperti dereferencing referensi nol
mendereferensi pointer non-null yang tidak valid dapat menghasilkan pengecualian itu dalam beberapa keadaan
Untuk memahami mengapa hal itu terjadi, ada baiknya untuk memahami bagaimana .NET menghasilkan pengecualian null dereference di tempat pertama. (Detail ini berlaku untuk .NET yang berjalan di Windows; sistem operasi lain menggunakan mekanisme serupa.)
Memori tervirtualisasi dalam Windows; setiap proses mendapatkan ruang memori virtual dari banyak "halaman" memori yang dilacak oleh sistem operasi. Setiap halaman memori memiliki flag yang ditetapkan di atasnya yang menentukan bagaimana penggunaannya: membaca dari, ditulis ke, dieksekusi, dan sebagainya. The terendah halaman ditandai sebagai "menghasilkan kesalahan jika pernah digunakan dengan cara apapun".
Baik penunjuk nol maupun referensi nol C#secara internal direpresentasikan sebagai angka nol, dan setiap upaya untuk merujuknya ke penyimpanan memori yang sesuai menyebabkan sistem operasi menghasilkan kesalahan. The .NET runtime kemudian mendeteksi kesalahan ini dan mengubahnya menjadi pengecualian null dereference.
Itu sebabnya dereferencing baik pointer nol dan referensi nol menghasilkan pengecualian yang sama.
Bagaimana dengan poin kedua? Dereferencing setiap pointer tidak valid yang jatuh di halaman terendah memori virtual menyebabkan kesalahan sistem operasi yang sama, dan dengan demikian pengecualian yang sama.
Mengapa ini masuk akal? Nah, misalkan kita memiliki struct yang berisi dua int, dan pointer yang tidak dikelola sama dengan nol. Jika kami mencoba melakukan dereferensi int kedua di struct, ia CLRtidak akan mencoba mengakses penyimpanan di lokasi nol; itu akan mengakses penyimpanan di lokasi empat. Tapi secara logis ini adalah dereferensi nol karena kita mendapatkan alamat itu melalui nol.
Jika Anda bekerja dengan kode yang tidak aman dan Anda mendapatkan pengecualian null dereference, perlu diketahui bahwa pointer yang menyinggung tidak harus nol. Ini dapat berupa lokasi apa pun di halaman terendah, dan pengecualian ini akan dibuat.
Mungkin ini adalah komentar bodoh tetapi bukankah cara pertama dan terbaik untuk menghindari masalah ini adalah dengan menginisialisasi objek? Bagi saya jika kesalahan ini terjadi biasanya karena saya lupa menginisialisasi sesuatu seperti elemen array. Saya pikir itu jauh lebih umum untuk mendefinisikan objek sebagai nol dan kemudian referensi. Mungkin berikan cara untuk menyelesaikan setiap masalah yang berbatasan dengan deskripsi. Masih posting yang bagus.
JPK
30
Bagaimana jika tidak ada objek, melainkan nilai pengembalian dari metode atau properti?
John Saunders
6
Contoh buku / penulis agak aneh .... Bagaimana itu bahkan mengkompilasi? Bagaimana cara kerja Intellisense? Apa ini saya tidak baik dengan computar ...
5
@ Akan: apakah edit saya yang terakhir membantu? Jika tidak, maka harap lebih eksplisit tentang apa yang Anda lihat sebagai masalah.
John Saunders
6
@ JohnSaunders Oh, tidak, maaf, maksudku versi penginisialisasi objek itu. new Book { Author = { Age = 45 } };Bagaimana bahkan inisialisasi batin ... Saya tidak bisa memikirkan situasi di mana init dalam akan pernah bekerja, namun itu mengkompilasi dan intellisense bekerja ... Kecuali untuk struct?
311
Pengecualian NullReference - Visual Basic
The NullReference Exceptionuntuk Visual Basic tidak berbeda dari yang ada di C # . Bagaimanapun, mereka berdua melaporkan pengecualian yang sama yang didefinisikan dalam .NET Framework yang keduanya gunakan. Penyebab unik untuk Visual Basic jarang terjadi (mungkin hanya satu).
Jawaban ini akan menggunakan istilah, sintaks, dan konteks Visual Basic. Contoh yang digunakan berasal dari sejumlah besar pertanyaan Stack Overflow sebelumnya. Ini untuk memaksimalkan relevansi dengan menggunakan jenis situasi yang sering terlihat di posting. Penjelasan lebih banyak juga disediakan bagi mereka yang mungkin membutuhkannya. Contoh yang mirip dengan milik Anda sangat mungkin tercantum di sini.
catatan:
Ini berbasis konsep: tidak ada kode untuk Anda tempel ke proyek Anda. Ini dimaksudkan untuk membantu Anda memahami apa yang menyebabkan NullReferenceException(NRE), cara menemukannya, cara memperbaikinya, dan bagaimana cara menghindarinya. NRE dapat disebabkan banyak cara sehingga ini tidak mungkin menjadi satu-satunya pertemuan Anda.
Contoh-contoh (dari posting Stack Overflow) tidak selalu menunjukkan cara terbaik untuk melakukan sesuatu.
Biasanya, obat paling sederhana digunakan.
Arti Dasar
Pesan "Objek tidak disetel ke instance Objek" berarti Anda mencoba menggunakan objek yang belum diinisialisasi. Ini bermuara pada salah satu dari ini:
Kode Anda menyatakan variabel objek, tetapi tidak menginisialisasi (buat instance atau ' instantiate ' itu)
Sesuatu yang diasumsikan kode Anda akan menginisialisasi objek, tidak
Mungkin, kode lain secara prematur membatalkan objek yang masih digunakan
Menemukan Penyebabnya
Karena masalahnya adalah referensi objek Nothing, jawabannya adalah memeriksa mereka untuk mengetahui yang mana. Kemudian tentukan mengapa itu tidak diinisialisasi. Pegang mouse di atas berbagai variabel dan Visual Studio (VS) akan menunjukkan nilainya - biang keladinya Nothing.
Anda juga harus menghapus blok Coba / Tangkap dari kode yang relevan, terutama yang tidak ada di blok Tangkap. Ini akan menyebabkan kode Anda mogok ketika mencoba menggunakan objek yang Nothing. Ini yang Anda inginkan karena akan mengidentifikasi lokasi pasti masalah, dan memungkinkan Anda mengidentifikasi objek yang menyebabkannya.
A MsgBoxdi Catch yang menampilkan Error while...akan sedikit membantu. Metode ini juga mengarah ke pertanyaan Stack Overflow yang sangat buruk , karena Anda tidak dapat mendeskripsikan pengecualian aktual, objek yang terlibat, atau bahkan baris kode tempat terjadinya.
Anda juga dapat menggunakan Locals Window( Debug -> Windows -> Locals ) untuk memeriksa objek Anda.
Setelah Anda tahu apa dan di mana masalahnya, biasanya cukup mudah untuk memperbaiki dan lebih cepat daripada mengirim pertanyaan baru.
Dim reg As CashRegister
...
TextBox1.Text = reg.Amount ' NRE
Masalahnya adalah bahwa Dimitu tidak membuat objek CashRegister ; itu hanya mendeklarasikan variabel bernama regTipe itu. Mendeklarasikan variabel objek dan membuat instance adalah dua hal yang berbeda.
Obat
The NewOperator sering dapat digunakan untuk membuat contoh ketika Anda menyatakan hal itu:
Dim reg AsNew CashRegister ' [New] creates instance, invokes the constructor' Longer, more explicit form:Dim reg As CashRegister =New CashRegister
Catatan: Jangan gunakan Dimlagi dalam prosedur, termasuk konstruktor ( Sub New):
Private reg As CashRegister
'...PublicSubNew()'...Dim reg AsNew CashRegister
EndSub
Ini akan membuat variabel lokalreg ,, yang hanya ada dalam konteks (sub). The regvariabel dengan tingkat modul Scopeyang akan Anda gunakan sisa-sisa di tempat lain Nothing.
Kehilangan Newoperator adalah penyebab # 1 yangNullReference Exceptions terlihat dalam pertanyaan Stack Overflow yang ditinjau.
Visual Basic mencoba memperjelas proses berulang kali menggunakan New: Menggunakan NewOperator menciptakan objek baru dan panggilan Sub New- konstruktor - di mana objek Anda dapat melakukan inisialisasi lainnya.
Untuk menjadi jelas, Dim(atau Private) hanya mendeklarasikan variabel dan variabelnya Type. The Lingkup variabel - apakah itu ada untuk seluruh modul / kelas atau lokal untuk prosedur - ditentukan oleh di mana ia dideklarasikan. Private | Friend | Publicmendefinisikan tingkat akses, bukan Lingkup .
Array ini hanya dideklarasikan, tidak dibuat. Ada beberapa cara untuk menginisialisasi array:
Private arr asString()=NewString(10){}' orPrivate arr()AsString=NewString(10){}' For a local array (in a procedure) and using 'Option Infer':Dim arr =NewString(10){}
Catatan: Dimulai dengan VS 2010, ketika menginisialisasi array lokal menggunakan literal dan Option Infer, elemen As <Type>dan Newopsional:
Dim myDbl AsDouble()={1.5,2,9.9,18,3.14}Dim myDbl =NewDouble(){1.5,2,9.9,18,3.14}Dim myDbl()={1.5,2,9.9,18,3.14}
Tipe data dan ukuran array disimpulkan dari data yang ditugaskan. Tingkat deklarasi kelas / Modul masih memerlukan As <Type>dengan Option Strict:
Private myDoubles AsDouble()={1.5,2,9.9,18,3.14}
Contoh: Array objek kelas
Dim arrFoo(5)As Foo
For i AsInteger=0To arrFoo.Count -1
arrFoo(i).Bar = i *10' ExceptionNext
Array telah dibuat, tetapi Fooobjek di dalamnya belum.
Obat
For i AsInteger=0To arrFoo.Count -1
arrFoo(i)=New Foo()' Create Foo instance
arrFoo(i).Bar = i *10Next
Menggunakan List(Of T)akan membuatnya sangat sulit untuk memiliki elemen tanpa objek yang valid:
Dim FooList AsNew List(Of Foo)' List created, but it is emptyDim f As Foo ' Temporary variable for the loopFor i AsInteger=0To5
f =New Foo()' Foo instance created
f.Bar = i *10
FooList.Add(f)' Foo object added to listNext
Koleksi .NET (yang ada banyak varietas - Daftar, Kamus, dll.) Juga harus dipakai atau dibuat.
Private myList As List(Of String)..
myList.Add("ziggy")' NullReference
Anda mendapatkan pengecualian yang sama karena alasan yang sama - myListhanya dideklarasikan, tetapi tidak ada instance yang dibuat. Obatnya sama:
myList =New List(Of String)' Or create an instance when declared:Private myList AsNew List(Of String)
Pengawasan umum adalah kelas yang menggunakan koleksi Type:
PublicClass Foo
Private barList As List(Of Bar)FriendFunction BarCount AsIntegerReturn barList.Count
EndFunctionFriendSub AddItem(newBar As Bar)If barList.Contains(newBar)=FalseThen
barList.Add(newBar)EndIfEndFunction
Setiap prosedur akan menghasilkan NRE, karena barListhanya dideklarasikan, tidak dipakai. Menciptakan instance Footidak akan juga membuat instance internal barList. Mungkin maksud untuk melakukan ini di konstruktor:
PublicSubNew' Constructor' Stuff to do when a new Foo is created...
barList =New List(Of Bar)EndSub
Seperti sebelumnya, ini tidak benar:
PublicSubNew()' Creates another barList local to this procedureDim barList AsNew List(Of Bar)EndSub
Bekerja dengan database hadiah banyak kesempatan untuk NullReference karena akan ada banyak benda ( Command, Connection, Transaction, Dataset, DataTable, DataRows....) digunakan sekaligus. Catatan: Tidak masalah penyedia data mana yang Anda gunakan - MySQL, SQL Server, OleDB, dll - konsep sama.
Contoh 1
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows AsInteger
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
Seperti sebelumnya, dsobjek Dataset dideklarasikan, tetapi sebuah instance tidak pernah dibuat. The DataAdapterakan mengisi yang ada DataSet, tidak membuat satu. Dalam hal ini, karena dsmerupakan variabel lokal, IDE memperingatkan Anda bahwa ini mungkin terjadi:
Ketika dideklarasikan sebagai variabel tingkat modul / kelas, seperti yang terlihat dengan kasus con, kompiler tidak dapat mengetahui apakah objek itu dibuat oleh prosedur hulu. Jangan abaikan peringatan.
Sebuah kesalahan ketik adalah masalah di sini: Employeesvs Employee. Tidak ada DataTablenama "Karyawan" yang dibuat, jadi suatu NullReferenceExceptionhasil mencoba mengaksesnya. Masalah potensial lainnya adalah dengan asumsi akan ada Itemsyang mungkin tidak terjadi ketika SQL menyertakan klausa WHERE.
Obat
Karena ini menggunakan satu tabel, penggunaan Tables(0)akan menghindari kesalahan ejaan. Memeriksa Rows.Countjuga dapat membantu:
If ds.Tables(0).Rows.Count >0Then
txtID.Text = ds.Tables(0).Rows(0).Item(1)
txtID.Name = ds.Tables(0).Rows(0).Item(2)EndIf
Filladalah fungsi mengembalikan jumlah yang Rowsterpengaruh yang juga dapat diuji:
If da.Fill(ds,"Employees")>0Then...
Contoh 3
Dim da AsNew 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 AsNew DataSet
da.Fill(ds)If ds.Tables("TICKET_RESERVATION").Rows.Count >0Then
The DataAdapterakan memberikan TableNamesseperti yang ditunjukkan pada contoh sebelumnya, tetapi tidak nama parse dari SQL atau database meja. Hasil dari,ds.Tables("TICKET_RESERVATION") referensi tabel tidak ada.
The Remedy adalah sama, referensi tabel dengan indeks:
Kode hanya menguji Itemssementara keduanya myFoodan Barmungkin juga Tidak Ada. The obat adalah untuk menguji seluruh rantai atau jalur objek satu per satu:
AndAlsopenting. Tes selanjutnya tidak akan dilakukan setelah Falsekondisi pertama ditemui. Ini memungkinkan kode untuk dengan aman 'menelusuri' ke objek satu tingkat di satu waktu, mengevaluasi myFoo.Barhanya setelah (dan jika) myFooditentukan valid. Rantai atau lintasan objek bisa menjadi cukup lama ketika mengkode objek kompleks:
Di sini, myWebBrowseratau Documentbisa jadi Tidak ada atau formfld1elemen mungkin tidak ada.
Kontrol UI
Dim cmd5 AsNew 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)
Antara lain, kode ini tidak mengantisipasi bahwa pengguna mungkin tidak memilih sesuatu dalam satu atau lebih kontrol UI. ListBox1.SelectedItemmungkin Nothing, jadi ListBox1.SelectedItem.ToStringakan menghasilkan NRE.
Obat
Validasi data sebelum menggunakannya (juga gunakan Option Strictdan parameter SQL):
Dim expiry As DateTime ' for text date validationIf(ComboBox5.SelectedItems.Count >0)AndAlso(ListBox1.SelectedItems.Count >0)AndAlso(ComboBox2.SelectedItems.Count >0)AndAlso(DateTime.TryParse(expiry.Text, expiry)Then'... do stuffElse
MessageBox.Show(...error message...)EndIf
Atau, Anda dapat menggunakan (ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Bentuk Visual Basic
PublicClass 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 AsNew List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}' Immediate NRE:Private somevar AsString=Me.Controls("TextBox1").Text
Ini adalah cara yang cukup umum untuk mendapatkan NRE. Dalam C #, tergantung pada bagaimana dikodekan, IDE akan melaporkan yang Controlstidak ada dalam konteks saat ini, atau "tidak dapat merujuk anggota non-statis". Jadi, sampai batas tertentu, ini hanya situasi VB. Ini juga kompleks karena dapat mengakibatkan kegagalan kaskade.
Array dan koleksi tidak dapat diinisialisasi dengan cara ini. Kode inisialisasi ini akan berjalan sebelum konstruktor membuat Formatau Controls. Hasil dari:
Daftar dan Koleksi hanya akan kosong
Array akan berisi lima elemen dari Nothing
The somevartugas akan menghasilkan NRE segera karena ada tidak memiliki .Textproperti
Merujuk elemen array nanti akan menghasilkan NRE. Jika Anda melakukan ini Form_Load, karena bug aneh, IDE tidak dapat melaporkan pengecualian ketika itu terjadi. Pengecualian akan muncul nanti ketika kode Anda mencoba menggunakan array. "Pengecualian sunyi" ini dirinci dalam pos ini . Untuk tujuan kami, kuncinya adalah bahwa ketika sesuatu bencana terjadi saat membuat formulir ( Sub Newatau Form Loadperistiwa), pengecualian mungkin tidak dilaporkan, kode keluar dari prosedur dan hanya menampilkan formulir.
Karena tidak ada kode lain di Anda Sub Newatau Form Loadacara akan berjalan setelah NRE tersebut, banyak hal lain dapat dibiarkan uninitialized.
Sub Form_Load(..._
'...Dim name AsString= NameBoxes(2).Text ' NRE' ...' More code (which will likely not be executed)' ...EndSub
Catatan ini berlaku untuk setiap dan semua kontrol dan referensi komponen membuat ini ilegal di mana mereka berada:
Sangat mengherankan bahwa VB tidak memberikan peringatan, tetapi obatnya adalah dengan mendeklarasikan kontainer pada level form, tetapi menginisialisasi mereka dalam form load event handler ketika kontrol benar-benar ada. Ini dapat dilakukan Sub Newselama kode Anda setelah InitializeComponentpanggilan:
' Module level declarationPrivate NameBoxes as TextBox()Private studentName AsString' 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
Kode array mungkin belum keluar dari hutan. Kontrol apa pun yang ada dalam kontrol wadah (seperti a GroupBoxatau Panel) tidak akan ditemukan di Me.Controls; mereka akan berada di koleksi Kontrol Panel atau GroupBox itu. Kontrol juga tidak akan dikembalikan ketika nama kontrol salah eja ( "TeStBox2"). Dalam kasus seperti itu, Nothingsekali lagi akan disimpan dalam elemen array tersebut dan NRE akan dihasilkan ketika Anda mencoba untuk referensi itu.
Ini seharusnya mudah ditemukan sekarang setelah Anda tahu apa yang Anda cari:
"Button2" berada di a Panel
Obat
Daripada referensi tidak langsung dengan nama menggunakan Controlskoleksi formulir , gunakan referensi kontrol:
' DeclarationPrivate 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...})
Tidak Mengembalikan Fungsi
Private bars AsNew List(Of Bars)' Declared and createdPublicFunction BarList()As List(Of Bars)
bars.Clear
If someCondition ThenFor n AsInteger=0to someValue
bars.Add(GetBar(n))Next n
ElseExitFunctionEndIfReturn bars
EndFunction
Ini adalah kasus di mana IDE akan memperingatkan Anda bahwa ' tidak semua jalur mengembalikan nilai dan NullReferenceExceptionhasil dapat '. Anda dapat menekan peringatan, dengan mengganti Exit Functiondengan Return Nothing, tetapi itu tidak memecahkan masalah. Apa pun yang mencoba menggunakan pengembalian ketika someCondition = Falseakan menghasilkan NRE:
bList = myFoo.BarList()ForEach b As Bar in bList ' EXCEPTION...
Obat
Ganti Exit Functionfungsi dengan Return bList. Mengembalikan kosongList tidak sama dengan mengembalikan Nothing. Jika ada kemungkinan objek yang dikembalikan dapat Nothing, uji sebelum menggunakannya:
Coba / Tangkap yang Diimplementasikan dengan Buruk
Try / Catch yang diimplementasikan dengan buruk dapat menyembunyikan di mana masalahnya dan menghasilkan yang baru:
Dim dr As SqlDataReader
TryDim lnk As LinkButton = TryCast(sender, LinkButton)Dim gr As GridViewRow =DirectCast(lnk.NamingContainer, GridViewRow)Dim eid AsString= 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()EndIf
command =New SqlCommand(sqlQry, connection)'More code fooing and barring
dr = command.ExecuteReader()If dr.Read()Then
lblFirstName.Text = Convert.ToString(dr("FirstName"))...EndIf
mpe.Show()CatchFinally
command.Dispose()
dr.Close()' <-- NRE
connection.Close()EndTry
Ini adalah kasus objek tidak dibuat seperti yang diharapkan, tetapi juga menunjukkan manfaat kontra dari yang kosong Catch.
Ada koma tambahan di SQL (setelah 'alamat surat') yang menghasilkan pengecualian di .ExecuteReader. Setelah Catchtidak melakukan apa-apa, Finallycobalah untuk melakukan pembersihan, tetapi karena Anda tidak dapat objek Closenol DataReader, NullReferenceExceptionhasil baru .
CatchBlok kosong adalah taman bermain iblis. OP ini bingung mengapa dia mendapatkan NRE di Finallyblok. Dalam situasi lain, sebuah kekosongan Catchdapat mengakibatkan sesuatu yang lebih jauh ke hilir menjadi berantakan dan menyebabkan Anda menghabiskan waktu melihat hal-hal yang salah di tempat yang salah untuk masalah tersebut. ("Pengecualian sunyi" yang dijelaskan di atas memberikan nilai hiburan yang sama.)
Obat
Jangan gunakan blok Coba / Tangkap kosong - biarkan kode macet sehingga Anda dapat a) mengidentifikasi penyebab b) mengidentifikasi lokasi dan c) menerapkan obat yang tepat. Blok Coba / Tangkap tidak dimaksudkan untuk menyembunyikan pengecualian dari orang yang memiliki kualifikasi unik untuk memperbaikinya - pengembang.
DBNull tidak sama dengan Tidak Ada
ForEach row As DataGridViewRow In dgvPlanning.Rows
IfNot IsDBNull(row.Cells(0).Value)Then...
The IsDBNullFungsi ini digunakan untuk menguji apakah nilai sama System.DBNull: Dari MSDN:
Nilai System.DBNull menunjukkan bahwa Objek mewakili data yang hilang atau tidak ada. DBNull tidak sama dengan Tidak Ada, yang menunjukkan bahwa variabel belum diinisialisasi.
Obat
If row.Cells(0) IsNot NothingThen...
Seperti sebelumnya, Anda dapat menguji Tidak Ada, kemudian untuk nilai tertentu:
Dim getFoo =(From f In dbContext.FooBars
Where f.something = something
Select f).FirstOrDefault
IfNot IsDBNull(getFoo)ThenIf IsDBNull(getFoo.user_id)Then
txtFirst.Text = getFoo.first_name
Else...
FirstOrDefaultmengembalikan item pertama atau nilai default, yang Nothinguntuk tipe referensi dan tidak pernah DBNull:
If getFoo IsNot NothingThen...
Kontrol
Dim chk As CheckBox
chk =CType(Me.Controls(chkName), CheckBox)If chk.Checked ThenReturn chk
EndIf
Jika sebuah CheckBoxdengan chkNametidak dapat ditemukan (atau ada di a GroupBox), maka chkakan menjadi Apa-apa dan berusaha untuk referensi properti apa pun akan menghasilkan pengecualian.
Obat
If(chk IsNot Nothing)AndAlso(chk.Checked)Then...
DataGridView
DGV memiliki beberapa kebiasaan yang dilihat secara berkala:
Jika dgvBookssudah AutoGenerateColumns = True, itu akan membuat kolom, tetapi tidak menamai mereka, jadi kode di atas gagal ketika referensi mereka dengan nama.
Obat
Beri nama kolom secara manual, atau referensi berdasarkan indeks:
Ketika Anda DataGridViewmemiliki AllowUserToAddRowsas True(default), Cellsbaris kosong / baru di bagian bawah semuanya akan berisi Nothing. Sebagian besar upaya untuk menggunakan konten (misalnya, ToString) akan menghasilkan NRE.
Obat
Gunakan For/Eachperulangan dan uji IsNewRowproperti untuk menentukan apakah itu baris terakhir. Ini berfungsi baik AllowUserToAddRowsbenar atau tidak:
ForEach r As DataGridViewRow in myDGV.Rows
If r.IsNewRow =FalseThen' ok to use this row
Jika Anda menggunakan For nloop, modifikasi jumlah baris atau gunakan Exit Forkapan IsNewRowbenar.
Pengaturan Saya (StringCollection)
Dalam keadaan tertentu, mencoba menggunakan item My.Settingsyang StringCollectiondapat menghasilkan NullReference saat pertama kali Anda menggunakannya. Solusinya sama, tetapi tidak sejelas itu. Mempertimbangkan:
My.Settings.FooBars.Add("ziggy")' foobars is a string collection
Karena VB mengelola Pengaturan untuk Anda, masuk akal untuk mengharapkannya untuk menginisialisasi koleksi. Itu akan, tetapi hanya jika Anda sebelumnya telah menambahkan entri awal ke koleksi (di Editor pengaturan). Karena koleksi (tampaknya) diinisialisasi ketika item ditambahkan, ia tetap Nothingketika tidak ada item dalam editor Pengaturan untuk ditambahkan.
Obat
Inisialisasi koleksi pengaturan di Loadpengendali acara formulir , jika / ketika dibutuhkan:
If My.Settings.FooBars IsNothingThen
My.Settings.FooBars =New System.Collections.Specialized.StringCollection
EndIf
Biasanya, Settingskoleksi hanya perlu diinisialisasi saat pertama kali aplikasi dijalankan. Obat alternatif adalah menambahkan nilai awal ke koleksi Anda di Proyek -> Pengaturan | FooBars , simpan proyek, lalu hapus nilai palsu.
Poin-Poin Utama
Anda mungkin lupa Newoperatornya.
atau
Sesuatu yang Anda asumsikan akan tampil sempurna untuk mengembalikan objek yang diinisialisasi ke kode Anda, tidak.
Jangan abaikan peringatan kompiler (selalu) dan gunakan Option Strict On(selalu).
Skenario lain adalah ketika Anda melemparkan objek nol ke dalam tipe nilai . Misalnya, kode di bawah ini:
object o =null;DateTime d =(DateTime)o;
Ini akan melempar NullReferenceExceptionpada pemain. Tampaknya cukup jelas dalam sampel di atas, tetapi ini dapat terjadi dalam skenario rumit yang lebih "mengikat" di mana objek null telah dikembalikan dari beberapa kode yang tidak Anda miliki, dan para pemain misalnya dihasilkan oleh beberapa sistem otomatis.
Salah satu contohnya adalah fragmen pengikat ASP.NET sederhana ini dengan kontrol Kalender:
Di sini, SelectedDatesebenarnya adalah properti - DateTimetipe - dari Calendartipe Kontrol Web, dan pengikatan dengan sempurna dapat mengembalikan sesuatu yang nol. ASP.NET Generator implisit akan membuat sepotong kode yang akan setara dengan kode pemain di atas. Dan ini akan meningkatkan NullReferenceExceptionyang cukup sulit dikenali, karena terletak pada kode ASP.NET yang dihasilkan yang mengkompilasi ...
Itu akan membuang kesalahan karena sementara saya sudah mendeklarasikan variabel " connection", itu tidak menunjuk ke apa pun. Ketika saya mencoba memanggil anggota " Open", tidak ada referensi untuk diselesaikan, dan itu akan menimbulkan kesalahan.
Untuk menghindari kesalahan ini:
Selalu inisialisasi objek Anda sebelum Anda mencoba melakukan apa pun dengannya.
Jika Anda tidak yakin apakah objek tersebut null, periksa dengan object == null.
Alat Resharper JetBrains akan mengidentifikasi setiap tempat dalam kode Anda yang memiliki kemungkinan kesalahan referensi nol, memungkinkan Anda untuk memasukkan cek nol. Kesalahan ini adalah sumber bug nomor satu, IMHO.
Alat Resharper JetBrains akan mengidentifikasi setiap tempat dalam kode Anda yang memiliki kemungkinan kesalahan referensi nol. Ini salah. Saya punya solusi tanpa deteksi itu, namun kode terkadang menghasilkan pengecualian. Saya menduga kadang-kadang tidak terdeteksi - setidaknya oleh mereka - ketika multithreading terlibat, tetapi saya tidak dapat berkomentar lebih lanjut karena saya belum mengidentifikasi lokasi bug saya.
j riv
Tapi bagaimana cara mengatasinya ketika NullReferenceException datang di usign HttpContext.Current.Responce.Clear (). Itu tidak diselesaikan dengan salah satu solusi di atas. karena ketika membuat objek objeknya dari HttpContext maka muncul kesalahan "Resolusi overload gagal karena tidak dapat diakses 'Baru' menerima Jumlah argumen ini.
Sunny Sandeep
158
Ini berarti kode Anda menggunakan variabel referensi objek yang disetel ke nol (artinya tidak mereferensikan instance objek aktual).
Untuk mencegah kesalahan, objek yang bisa null harus diuji untuk null sebelum digunakan.
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}
Perlu diketahui bahwa terlepas dari skenario, penyebabnya selalu sama di .NET:
Anda mencoba menggunakan variabel referensi yang nilainya adalah Nothing/ null. Ketika nilainya adalah Nothing/ nulluntuk variabel referensi, itu berarti ia tidak benar-benar memegang referensi ke instance objek apa pun yang ada di heap.
Anda tidak pernah menugaskan sesuatu ke variabel, tidak pernah membuat instance dari nilai yang diberikan ke variabel, atau Anda mengatur variabel sama dengan Nothing/ nullsecara manual, atau Anda memanggil fungsi yang mengatur variabel ke Nothing/ nulluntuk Anda.
Contoh pengecualian ini yang dilemparkan adalah: Ketika Anda mencoba untuk memeriksa sesuatu, itu adalah nol.
Sebagai contoh:
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}
The .NET runtime akan melempar NullReferenceException ketika Anda mencoba untuk melakukan suatu tindakan pada sesuatu yang belum dipakai misalnya kode di atas.
Dibandingkan dengan ArgumentNullException yang biasanya dilemparkan sebagai tindakan defensif jika suatu metode mengharapkan bahwa apa yang diteruskan ke sana bukan nol.
C # 8.0 memperkenalkan jenis referensi yang dapat dibatalkan dan jenis referensi yang tidak dapat dibatalkan . Jadi hanya jenis referensi yang dapat dibatalkan yang harus diperiksa untuk menghindari NullReferenceException .
Jika Anda belum menginisialisasi tipe referensi, dan Anda ingin mengatur atau membaca salah satu propertinya, ia akan melempar NullReferenceException .
Contoh:
Person p =null;
p.Name="Harry";// NullReferenceException occurs here.
Anda bisa menghindari ini dengan memeriksa apakah variabelnya bukan nol:
Person p =null;if(p!=null){
p.Name="Harry";// Not going to run to this point}
Untuk memahami sepenuhnya mengapa NullReferenceException dilemparkan, penting untuk mengetahui perbedaan antara tipe nilai dan [tipe referensi] [3].
Jadi, jika Anda berurusan dengan tipe nilai , NullReferenceExceptions tidak dapat terjadi. Meskipun Anda harus tetap waspada ketika berhadapan dengan jenis referensi !
Hanya tipe referensi, seperti yang disarankan namanya, dapat menahan referensi atau menunjukkan apa-apa (atau 'nol'). Sedangkan tipe nilai selalu mengandung nilai.
-1: karena pertanyaannya adalah "Apa itu NullReferenceException", tipe nilai tidak relevan.
John Saunders
21
@ John Saunders: Saya tidak setuju. Sebagai pengembang perangkat lunak, sangat penting untuk dapat membedakan antara nilai dan jenis referensi. kalau tidak orang lain akan memeriksa apakah bilangan bulat adalah nol.
Fabian Bigler
5
Benar, hanya saja tidak dalam konteks pertanyaan ini.
John Saunders
4
Terima kasih atas petunjuknya. Saya memperbaikinya sedikit dan menambahkan contoh di atas. Saya masih berpikir menyebutkan Referensi & Jenis Nilai berguna.
Fabian Bigler
5
Saya pikir Anda belum menambahkan apa pun yang tidak ada di jawaban lain, karena pertanyaan sebelumnya mengandaikan jenis referensi.
John Saunders
78
Kasus lain yang NullReferenceExceptionsdapat terjadi adalah penggunaan (salah) asoperator :
Di sini, Bookdan Carmerupakan tipe yang tidak kompatibel; a Cartidak dapat dikonversi / dilemparkan ke a Book. Ketika para pemeran ini gagal, askembali null. Penggunaan mybooksetelah ini menyebabkan a NullReferenceException.
Secara umum, Anda harus menggunakan gips atau as, sebagai berikut:
Jika Anda mengharapkan konversi tipe selalu berhasil (mis. Anda tahu objek apa yang harus ada sebelumnya), maka Anda harus menggunakan pemeran:
ComicBook cb =(ComicBook)specificBook;
Jika Anda tidak yakin dengan jenisnya, tetapi Anda ingin mencoba menggunakannya sebagai jenis tertentu, maka gunakan as:
Ini bisa sering terjadi ketika membuka kotak variabel. Saya menemukan itu sering terjadi di penangan acara setelah saya mengubah jenis elemen UI tetapi lupa untuk memperbarui kode-belakang.
Brendan
65
Anda menggunakan objek yang berisi referensi nilai nol. Jadi itu memberikan pengecualian nol. Dalam contoh nilai string adalah nol dan ketika memeriksa panjangnya, pengecualian terjadi.
Contoh:
stringvalue=null;if(value.Length==0)// <-- Causes exception{Console.WriteLine(value);// <-- Never reached}
Kesalahan pengecualian adalah:
Pengecualian Tidak Tertangani:
System.NullReferenceException: Referensi objek tidak disetel ke instance objek. di Program.Main ()
Sangat dalam! Saya tidak pernah menganggap konstanta 'nol' sebagai nilai referensi. Jadi ini adalah bagaimana C # mengabstraksikan "NullPointer" ya? B / c seperti yang saya ingat di C ++, NPE dapat disebabkan oleh penereferensian pointer yang tidak diinisialisasi (mis., Ketik ref di c #) yang nilai defaultnya adalah alamat yang tidak dialokasikan untuk proses itu (banyak kasus ini adalah 0, terutama di versi C + + yang melakukan inisialisasi otomatis, yang merupakan milik OS - f dengan itu dan mati beeotch (atau hanya menangkap sigkill OS menyerang proses Anda dengan)).
samis
64
Sementara apa yang menyebabkan NullReferenceExceptions dan pendekatan untuk menghindari / memperbaiki pengecualian tersebut telah diatasi dalam jawaban lain, apa yang belum dipelajari oleh banyak programmer adalah bagaimana cara secara independen men - debug pengecualian seperti itu selama pengembangan.
Sekarang, ketika NullReferenceException dilempar (atau tidak ditangani) debugger akan berhenti (ingat aturan yang ditetapkan di atas?) Pada baris di mana pengecualian terjadi. Terkadang kesalahan akan mudah dikenali.
Misalnya, pada baris berikut, satu-satunya kode yang dapat menyebabkan pengecualian adalah jika myStringbernilai nol. Ini dapat diverifikasi dengan melihat Jendela Tonton atau menjalankan ekspresi di Jendela Segera .
var x = myString.Trim();
Dalam kasus yang lebih maju, seperti berikut ini, Anda harus menggunakan salah satu teknik di atas (Tonton atau Segera Windows) untuk memeriksa ekspresi untuk menentukan apakah str1 itu nol atau jika str2itu nol.
var x = str1.Trim()+ str2.Trim();
Setelah di mana pengecualian adalah lemparan telah ditemukan, biasanya sepele untuk mundur alasan untuk mencari tahu di mana nilai null itu [salah] diperkenalkan -
Luangkan waktu yang dibutuhkan untuk memahami penyebab pengecualian. Periksa untuk ekspresi nol. Periksa ekspresi sebelumnya yang bisa menghasilkan ekspresi nol seperti itu. Tambahkan breakpoints dan melangkah melalui program yang sesuai.Gunakan debugger.
1 Jika Break on Throws terlalu agresif dan debugger berhenti pada NPE di pustaka .NET atau pihak ketiga, Break on User-Unhandled dapat digunakan untuk membatasi pengecualian yang tertangkap. Selain itu, VS2012 memperkenalkan Just My Code yang saya sarankan aktifkan juga.
Jika Anda men-debug dengan Just My Code diaktifkan, perilaku ini sedikit berbeda. Dengan Just My Code diaktifkan, debugger mengabaikan pengecualian runtime bahasa umum (CLR) kesempatan pertama yang dibuang di luar Kode Saya dan tidak melewati Kode Saya
object o =null;DateTime d =(DateTime)o;// NullReferenceException
di mana konversi unboxing (dilemparkan) dariobject (atau dari salah satu kelas System.ValueTypeatau System.Enum, atau dari tipe antarmuka) ke tipe nilai (selain Nullable<>) dengan sendirinya memberikan NullReferenceException.
Di arah lain, sebuah tinju konversi dari suatu Nullable<>yang memiliki HasValuesama falseuntuk tipe referensi, dapat memberikan nullreferensi yang kemudian dapat kemudian menyebabkan NullReferenceException. Contoh klasik adalah:
DateTime? d =null;var s = d.ToString();// OK, no exception (no boxing), returns ""var t = d.GetType();// Bang! d is boxed, NullReferenceException
Terkadang tinju terjadi dengan cara lain. Misalnya dengan metode ekstensi non-generik ini:
Menambahkan kasus ketika nama kelas untuk entitas yang digunakan dalam kerangka entitas sama dengan nama kelas untuk file kode-belakang formulir web.
Misalkan Anda memiliki formulir web Contact.aspx yang kelas codebehindnya adalah Kontak dan Anda memiliki nama entitas Kontak.
Kemudian kode berikut akan melempar NullReferenceException ketika Anda memanggil context.SaveChanges ()
Contact contact =newContact{Name="Abhinav"};var context =newDataContext();
context.Contacts.Add(contact);
context.SaveChanges();// NullReferenceException at this line
Kesalahan terjadi ketika kedua entitas dan kelas codebehind berada di namespace yang sama. Untuk memperbaikinya, ganti nama kelas entitas atau kelas kode kode untuk Contact.aspx.
Alasan
saya masih belum yakin tentang alasannya. Tetapi setiap kali kelas entitas akan memperpanjang System.Web.UI.Page kesalahan ini terjadi.
Kasus umum lain di mana orang mungkin menerima pengecualian ini melibatkan kelas mengejek selama pengujian unit. Terlepas dari kerangka mengejek yang digunakan, Anda harus memastikan bahwa semua level hirarki kelas yang sesuai diejek dengan benar. Secara khusus, semua properti dariHttpContext yang dirujuk oleh kode yang diuji harus diejek.
Saya memiliki perspektif berbeda untuk menjawab ini. Jawaban semacam ini "apa lagi yang bisa saya lakukan untuk menghindarinya? "
Ketika bekerja di berbagai lapisan , misalnya dalam aplikasi MVC, pengontrol membutuhkan layanan untuk memanggil operasi bisnis. Dalam skenario seperti itu, Dependency Injection Container dapat digunakan untuk menginisialisasi layanan untuk menghindari NullReferenceException . Jadi itu berarti Anda tidak perlu khawatir tentang memeriksa null dan cukup memanggil layanan dari controller seolah-olah mereka akan selalu tersedia (dan diinisialisasi) baik sebagai singleton atau prototipe.
publicclassMyController{privateServiceA serviceA;privateServiceB serviceB;publicMyController(ServiceA serviceA,ServiceB serviceB){this.serviceA = serviceA;this.serviceB = serviceB;}publicvoidMyMethod(){// 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();}}
-1: ini hanya menangani satu skenario - dependensi yang tidak diinisialisasi. Ini adalah skenario minoritas untuk NullReferenceException. Sebagian besar kasus adalah kesalahpahaman sederhana tentang cara kerja benda. Berikutnya yang paling sering adalah situasi lain di mana pengembang mengasumsikan bahwa objek akan diinisialisasi secara otomatis.
John Saunders
Ketergantungan injeksi umumnya tidak digunakan untuk menghindari NullReferenceException. Saya tidak percaya bahwa Anda telah menemukan skenario umum di sini. Dalam kasus apa pun, jika Anda mengedit jawaban Anda agar lebih bergaya stackoverflow.com/a/15232518/76337 , maka saya akan menghapus downvote.
John Saunders
38
Untuk masalah "apa yang harus saya lakukan" , ada banyak jawaban.
Cara yang lebih "formal" untuk mencegah kondisi kesalahan seperti itu saat mengembangkan adalah menerapkan desain dengan kontrak dalam kode Anda. Ini berarti Anda perlu mengatur kelas invarian , dan / atau bahkan fungsi / metode prasyarat dan postkondisi pada sistem Anda, sambil mengembangkan.
Singkatnya, invarian kelas memastikan bahwa akan ada beberapa kendala di kelas Anda yang tidak akan dilanggar dalam penggunaan normal (dan oleh karena itu, kelas tidak akan mendapatkan dalam keadaan tidak konsisten). Prasyarat berarti bahwa data yang diberikan sebagai input ke fungsi / metode harus mengikuti beberapa batasan yang ditetapkan dan tidak pernah melanggarnya, dan postkondisi berarti bahwa output fungsi / metode harus mengikuti batasan yang ditetapkan lagi tanpa pernah melanggarnya. Kondisi kontrak tidak boleh dilanggar selama pelaksanaan program bebas bug, oleh karena itu desain berdasarkan kontrak diperiksa dalam praktiknya dalam mode debug, sementara dinonaktifkan dalam rilis , untuk memaksimalkan kinerja sistem yang dikembangkan.
Dengan cara ini, Anda dapat menghindari NullReferenceExceptionkasus-kasus yang merupakan hasil pelanggaran terhadap batasan yang ditetapkan. Misalnya, jika Anda menggunakan properti objek Xdi kelas dan kemudian mencoba memanggil salah satu metode dan Xmemiliki nilai nol, maka ini akan mengarah ke NullReferenceException:
public X {get;set;}publicvoidInvokeX(){
X.DoSomething();// if X value is null, you will get a NullReferenceException}
Tetapi jika Anda menetapkan "properti X tidak boleh memiliki nilai nol" sebagai prasyarat metode, maka Anda dapat mencegah skenario yang dijelaskan sebelumnya:
//Using code contracts:[ContractInvariantMethod]protectedvoidObjectInvariant(){Contract.Invariant( X !=null);//...}
Untuk alasan ini, proyek Kontrak Kode ada untuk aplikasi .NET.
Atau, desain berdasarkan kontrak dapat diterapkan dengan menggunakan asersi .
Saya berpikir untuk menambahkan ini karena tidak ada yang menyebutkan ini, dan sejauh itu ada sebagai pendekatan, niat saya adalah untuk memperkaya topik.
Nick Louloudakis
2
Terima kasih telah memperkaya topik ini. Saya telah memberikan pendapat saya tentang penambahan Anda. Sekarang orang lain dapat melakukan hal yang sama.
John Saunders
2
Saya pikir ini adalah tambahan yang bermanfaat untuk topik yang diberikan bahwa ini adalah utas yang sangat dilihat. Saya pernah mendengar tentang kontrak kode sebelumnya dan ini adalah pengingat yang baik untuk mempertimbangkan menggunakannya.
VoteCoffee
36
A NullReferenceExceptiondilemparkan ketika kita mencoba mengakses Properti dari objek nol atau ketika nilai string menjadi kosong dan kita mencoba mengakses metode string.
Ini salah. String.Empty.ToLower()tidak akan melempar pengecualian referensi nol. Ini mewakili string aktual, meskipun yang kosong (yaitu ""). Karena ini memiliki objek untuk dipanggil ToLower(), tidak masuk akal untuk melempar pengecualian referensi nol di sana.
Saya mendapatkan Object reference not set to an instance of an object ketika saya mencoba menyajikan Tampilan dalam Tampilan dengan mengirimkannya Model, seperti ini:
@{MyEntity M =newMyEntity();}@RenderPage("_MyOtherView.cshtml", M);// error in _MyOtherView, the Model was Null
Debugging menunjukkan model itu Null di dalam MyOtherView. Sampai saya mengubahnya menjadi:
@{MyEntity M =newMyEntity();}@Html.Partial("_MyOtherView.cshtml", M);
Dan itu berhasil.
Selain itu, alasan saya tidak harus Html.Partialmemulainya adalah karena Visual Studio kadang-kadang melempar garis berlekuk-galat di bawah Html.Partialjika itu di dalam foreachloop yang dibangun secara berbeda , meskipun itu sebenarnya bukan kesalahan:
@inheritsSystem.Web.Mvc.WebViewPage@{ViewBag.Title="Entity Index";List<MyEntity>MyEntities=newList<MyEntity>();MyEntities.Add(newMyEntity());MyEntities.Add(newMyEntity());MyEntities.Add(newMyEntity());}<div>@{foreach(var M inMyEntities){// 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>
Tapi saya bisa menjalankan aplikasi tanpa masalah dengan "kesalahan" ini. Saya dapat menyingkirkan kesalahan dengan mengubah struktur foreachloop agar terlihat seperti ini:
@foreach(var M inMyEntities){...}
Meskipun saya merasa itu karena Visual Studio salah membaca tanda kurung dan kurung.
Juga, tolong tunjukkan baris mana yang melempar pengecualian, dan mengapa.
John Saunders
Kesalahan terjadi di MyOtherView.cshtml, yang tidak saya sertakan di sini, karena Model tidak dikirim dengan benar (itu Null), jadi saya tahu kesalahannya adalah bagaimana saya mengirim Model.
Travis Heeter
22
Apa yang bisa kamu lakukan?
Ada banyak jawaban bagus di sini yang menjelaskan referensi nol dan bagaimana men-debug-nya. Tetapi ada sangat sedikit tentang bagaimana mencegah masalah atau setidaknya membuatnya lebih mudah untuk ditangkap.
Periksa argumen
Sebagai contoh, metode dapat memeriksa argumen yang berbeda untuk melihat apakah mereka nol dan melempar ArgumentNullException, pengecualian yang jelas dibuat untuk tujuan yang tepat ini.
Konstruktor untuk ArgumentNullExceptioneven mengambil nama parameter dan pesan sebagai argumen sehingga Anda dapat memberi tahu pengembang apa masalahnya.
publicvoidDoSomething(MyObject obj){if(obj ==null){thrownewArgumentNullException("obj","Need a reference to obj.");}}
Gunakan Alat
Ada juga beberapa perpustakaan yang dapat membantu. "Resharper" misalnya dapat memberi Anda peringatan saat Anda menulis kode, terutama jika Anda menggunakan atributnya: NotNullAttribute
Ada "Kontrak Kode Microsoft" di mana Anda menggunakan sintaksis seperti Contract.Requires(obj != null)yang memberi Anda runtime dan kompilasi memeriksa: Memperkenalkan Kontrak Kode .
Ada juga "PostSharp" yang akan memungkinkan Anda untuk hanya menggunakan atribut seperti ini:
publicvoidDoSometing([NotNull] obj)
Dengan melakukan itu dan menjadikan PostSharp bagian dari proses build Anda objakan diperiksa nol pada saat runtime. Lihat: cek kosong PostSharp
Solusi Kode Biasa
Atau Anda selalu bisa mengkode pendekatan Anda sendiri menggunakan kode lama polos. Misalnya di sini adalah struct yang dapat Anda gunakan untuk menangkap referensi nol. Ini dimodelkan setelah konsep yang sama dengan Nullable<T>:
[System.Diagnostics.DebuggerNonUserCode]publicstructNotNull<T>where T:class{private T _value;public T Value{get{if(_value ==null){thrownewException("null value not allowed");}return _value;}set{if(value==null){thrownewException("null value not allowed.");}
_value =value;}}publicstaticimplicitoperator T(NotNull<T> notNullValue){return notNullValue.Value;}publicstaticimplicitoperatorNotNull<T>(T value){returnnewNotNull<T>{Value=value};}}
Anda akan menggunakan sangat mirip dengan cara yang sama Anda akan gunakan Nullable<T>, kecuali dengan tujuan mencapai yang sebaliknya - untuk tidak mengizinkan null. Berikut ini beberapa contohnya:
NotNull<Person> person =null;// throws exceptionNotNull<Person> person =newPerson();// OKNotNull<Person> person =GetPerson();// throws exception if GetPerson() returns null
NotNull<T>secara implisit dilemparkan ke dan dari Tsehingga Anda dapat menggunakannya di mana saja Anda membutuhkannya. Misalnya, Anda bisa meneruskan Personobjek ke metode yang mengambil NotNull<Person>:
Person person =newPerson{Name="John"};WriteName(person);publicstaticvoidWriteName(NotNull<Person> person){Console.WriteLine(person.Value.Name);}
Seperti yang Anda lihat di atas sebagai nullable, Anda akan mengakses nilai yang mendasarinya melalui Valueproperti. Atau, Anda dapat menggunakan gips eksplisit atau implisit, Anda dapat melihat contoh dengan nilai pengembalian di bawah:
Person person =GetPerson();publicstaticNotNull<Person>GetPerson(){returnnewPerson{Name="John"};}
Atau Anda bahkan dapat menggunakannya ketika metode baru saja kembali T(dalam hal ini Person) dengan melakukan gips. Misalnya, kode berikut hanya akan seperti kode di atas:
Person person =(NotNull<Person>)GetPerson();publicstaticPersonGetPerson(){returnnewPerson{Name="John"};}
Gabungkan dengan Extension
Kombinasikan NotNull<T>dengan metode ekstensi dan Anda dapat membahas lebih banyak situasi. Berikut adalah contoh tampilan metode ekstensi:
[System.Diagnostics.DebuggerNonUserCode]publicstaticclassNotNullExtension{publicstatic T NotNull<T>(this T @this)where T:class{if(@this==null){thrownewException("null value not allowed");}return@this;}}
Dan ini adalah contoh bagaimana itu bisa digunakan:
var person =GetPerson().NotNull();
GitHub
Untuk referensi Anda, saya membuat kode di atas tersedia di GitHub, Anda dapat menemukannya di:
C # 6.0 memperkenalkan "operator null-kondisional" yang sedikit membantu. Dengan fitur ini, Anda dapat mereferensikan objek bersarang dan jika salah satunya adalah nullkeseluruhan ekspresi yang dikembalikan null.
Ini mengurangi jumlah cek nol yang harus Anda lakukan dalam beberapa kasus. Sintaksnya adalah meletakkan tanda tanya sebelum setiap titik. Ambil kode berikut sebagai contoh:
var address = country?.State?.County?.City;
Bayangkan itu countryadalah objek tipe Countryyang memiliki properti yang disebut Statedan sebagainya. Jika country, State, County, atau Cityyang nullkemudian address will benol . Therefore you only have to check whetheralamat isnull`.
Ini fitur hebat, tetapi memberi Anda lebih sedikit informasi. Itu tidak membuatnya jelas yang mana dari 4 adalah nol.
Built-in seperti Nullable?
C # memiliki singkatan yang bagus untuk Nullable<T>, Anda dapat membuat sesuatu nullable dengan meletakkan tanda tanya setelah tipe seperti itu int?.
Akan lebih baik jika C # memiliki sesuatu seperti NotNull<T>struct di atas dan memiliki singkatan yang sama, mungkin tanda seru sehingga Anda bisa menulis sesuatu seperti (!): public void WriteName(Person! person).
NullReferenceException dimaksudkan untuk dibuang oleh CLR. Ini berarti bahwa referensi ke null telah terjadi. Itu tidak berarti bahwa referensi ke nol akan terjadi kecuali bahwa Anda secara cerdik memeriksa terlebih dahulu.
John Saunders
Saya mengerti maksud Anda tentang bagaimana hal itu membingungkan. Saya telah memperbaruinya menjadi pengecualian reguler untuk contoh ini dan pengecualian khusus di GitHub.
Luis Perez
Jawaban yang bagus untuk pertanyaan mendasar seperti itu. Ini tidak terlalu buruk ketika kode Anda gagal. Ini mengerikan ketika datang dari jauh di dalam suatu perpustakaan pihak ketiga komersial yang Anda andalkan, dan dukungan pelanggan terus bersikeras bahwa itu harus kode Anda yang menyebabkan masalah. Dan Anda tidak sepenuhnya yakin itu tidak dan seluruh proyek terhenti .. Saya benar-benar berpikir ini mungkin membuat tulisan di batu nisan yang sesuai untuk batu nisan saya: "Referensi objek tidak disetel ke instance objek."
Darrel Lee
10
Menariknya, tidak ada jawaban di halaman ini yang menyebutkan dua sisi tepi, harap tidak ada yang keberatan jika saya menambahkannya:
Kasus tepi # 1: akses bersamaan ke Kamus
Kamus umum di .NET tidak aman untuk thread dan kadang - kadang mereka melempar NullReferenceatau bahkan (lebih sering) aKeyNotFoundException ketika Anda mencoba mengakses kunci dari dua utas secara bersamaan. Pengecualian cukup menyesatkan dalam kasus ini.
Kasing tepi # 2: kode tidak aman
Jika NullReferenceExceptiondilemparkan oleh unsafekode, Anda mungkin melihat variabel pointer Anda, dan memeriksanyaIntPtr.Zero atau sesuatu. Yang merupakan hal yang sama ("pengecualian pointer nol"), tetapi dalam kode yang tidak aman, variabel sering dilemparkan ke tipe-nilai / array, dll., Dan Anda membenturkan kepala ke dinding, bertanya-tanya bagaimana tipe-nilai dapat membuang ini pengecualian.
(Alasan lain untuk tidak menggunakan kode tidak aman kecuali Anda memerlukannya, by the way)
Contoh kamus Anda bukan kasus tepi. Jika objek tidak aman, kemudian menggunakannya dari banyak utas menghasilkan hasil acak. Contoh kode tidak aman Anda berbeda nulldengan caranya?
John Saunders
10
Anda dapat memperbaiki NullReferenceException dengan cara yang bersih menggunakan Null-conditional Operator di c # 6 dan menulis lebih sedikit kode untuk menangani cek nol.
Ini digunakan untuk menguji nol sebelum melakukan operasi akses anggota (?) Atau indeks (? [).
Contoh
var name = p?.Spouse?.FirstName;
setara dengan:
if(p !=null){if(p.Spouse!=null){
name = p.Spouse.FirstName;}}
Hasilnya adalah bahwa nama akan menjadi nol ketika p adalah nol atau ketika p. Pasangan adalah nol.
Jika tidak, nama variabel akan diberi nilai p.Spouse.FirstName.
Baris kesalahan "Referensi objek tidak disetel ke instance objek." Menyatakan bahwa Anda belum menetapkan objek instance ke referensi objek dan Anda masih mengakses properies / metode objek itu.
misalnya: katakanlah Anda memiliki kelas yang disebut myClass dan mengandung satu properti prop1.
publicClass myClass
{publicint prop1 {get;set;}}
Sekarang Anda mengakses prop1 ini di beberapa kelas lain seperti di bawah ini:
publicclassDemo{publicvoid testMethod(){
myClass ref=null;ref.prop1 =1;//This line throws error}}
baris di atas melempar kesalahan karena referensi kelas myClass dideklarasikan tetapi tidak instantiated atau turunan objek tidak ditugaskan ke referecne dari kelas itu.
Untuk memperbaiki ini, Anda harus instantiate (menetapkan objek untuk referensi kelas itu).
Referensi NullReferenceException atau Obyek yang tidak disetel ke instance objek terjadi ketika objek kelas yang Anda coba gunakan tidak instantiated. Sebagai contoh:
Asumsikan bahwa Anda memiliki kelas bernama Siswa.
Seperti terlihat pada kode di atas, pernyataan
Siswa s - hanya menyatakan variabel tipe Siswa, perhatikan bahwa kelas Siswa tidak dipakai pada saat ini. Oleh karena itu, ketika pernyataan s.GetFullName () dijalankan, itu akan membuang NullReferenceException.
Anda mencoba mengakses objek yang tidak dibuat atau saat ini tidak ada dalam memori.
Jadi bagaimana cara mengatasinya:
Debug dan biarkan debugger istirahat ... Ini akan langsung membawa Anda ke variabel yang rusak ... Sekarang tugas Anda adalah hanya memperbaiki ini .. Menggunakan kata kunci baru di tempat yang tepat.
Jika itu disebabkan pada beberapa perintah database karena objek tidak ada maka yang perlu Anda lakukan adalah melakukan centang nol dan menanganinya:
if(i ==null){// Handle this}
Yang paling sulit .. jika GC mengumpulkan objek sudah ... Ini umumnya terjadi jika Anda mencoba untuk menemukan objek menggunakan string ... Artinya, menemukannya dengan nama objek maka dapat terjadi bahwa GC mungkin sudah membersihkannya ... Ini sulit ditemukan dan akan menjadi cukup masalah ... Cara yang lebih baik untuk mengatasi ini adalah melakukan pemeriksaan nol di mana pun diperlukan selama proses pengembangan. Ini akan menghemat banyak waktu.
Dengan mencari dengan nama saya maksudkan beberapa kerangka kerja memungkinkan Anda untuk FIndObjects menggunakan string dan kode mungkin terlihat seperti ini: FindObject ("ObjectName");
Jika Anda memiliki referensi ke suatu objek, maka GC tidak pernah membersihkannya
John Saunders
2
jika Anda menggunakan hal-hal seperti FindObject ("Nama Objek") tidak ada cara GC akan tahu sebelumnya bahwa Anda akan merujuk objek itu .. ini adalah apa yang sedang mencoba untuk menjelaskan .. ini terjadi saat runtime
Akash Gutha
2
Ada beberapa kerangka kerja yang menyediakan fungsionalitas ini di C # seperti Unity. pertanyaannya tidak ada hubungannya dengan BCl. Cari di Internet sebelum Mengkritik ada banyak fungsi seperti mereka dan untuk informasi baik saya bahkan menggunakannya setiap hari. Sekarang tolong beri tahu saya bagaimana jawabannya tidak masuk akal.
Contoh yang saya lihat di tautan Anda menetapkan hasil GameObject.Find ke bidang anggota. Itu referensi dan GC tidak akan mengumpulkannya sampai objek yang mengandung dikumpulkan.
John Saunders
1
Secara harfiah cara termudah untuk memperbaiki NullReferenceExeption memiliki dua cara. Jika Anda memiliki GameObject misalnya dengan skrip yang dilampirkan dan variabel bernama rb (rigidbody) variabel ini akan mulai nol ketika Anda memulai permainan.
Inilah sebabnya mengapa Anda mendapatkan NullReferenceExeption karena komputer tidak memiliki data yang disimpan dalam variabel itu.
Saya akan menggunakan variabel RigidBody sebagai contoh.
Kami dapat menambahkan data dengan sangat mudah sebenarnya dalam beberapa cara:
Tambahkan RigidBody ke objek Anda dengan AddComponent> Physics> Rigidbody
Kemudian masuk ke skrip Anda dan ketik rb = GetComponent<Rigidbody>();
Baris kode ini bekerja paling baik di bawah Anda Start()atauAwake() fungsi.
Anda dapat menambahkan komponen secara terprogram dan menetapkan variabel secara bersamaan dengan satu baris kode: rb = AddComponent<RigidBody>();
Catatan lebih lanjut: Jika Anda ingin kesatuan untuk menambahkan komponen ke objek Anda dan Anda mungkin lupa menambahkannya, Anda bisa mengetikkan di [RequireComponent(typeof(RigidBody))]atas deklarasi kelas Anda (ruang di bawah semua usings Anda).
Nikmati dan bersenang-senang membuat game!
Ini pada dasarnya adalah pengecualian referensi Null . Sebagai Microsoft menyatakan-
Pengecualian NullReferenceException dilemparkan ketika Anda mencoba mengakses anggota jenis yang nilainya nol.
Apa artinya?
Itu berarti jika ada anggota yang tidak memiliki nilai apa pun dan kami membuat anggota itu untuk melakukan tugas tertentu, maka sistem tidak diragukan lagi akan melemparkan pesan dan berkata-
"Hei, tunggu, anggota itu tidak memiliki nilai sehingga tidak bisa melakukan tugas yang kamu serahkan."
Pengecualian itu sendiri mengatakan bahwa sesuatu sedang dirujuk tetapi nilainya tidak ditetapkan. Jadi ini menunjukkan bahwa itu hanya terjadi saat menggunakan tipe referensi karena tipe Value tidak dapat dibatalkan.
NullReferenceException tidak akan terjadi jika kita menggunakan anggota tipe Nilai.
Kode di atas menunjukkan string sederhana yang ditugaskan dengan null nilai .
Sekarang, ketika saya mencoba untuk mencetak panjang string str , saya mendapatkan pengecualian yang tidak tertangani dari tipe 'System.NullReferenceException' terjadi pesan karena anggota str menunjuk ke nol dan tidak mungkin ada panjang nol.
' NullReferenceException ' juga terjadi ketika kita lupa untuk instantiate jenis referensi.
Misalkan saya memiliki metode kelas dan anggota di dalamnya. Saya belum membuat kelas saya tetapi hanya memberi nama kelas saya. Sekarang jika saya mencoba menggunakan metode ini, kompiler akan melemparkan kesalahan atau mengeluarkan peringatan (tergantung pada kompiler).
classProgram{staticvoidMain(string[] args){MyClass1 obj;
obj.foo();//Use of unassigned local variable 'obj'}}publicclassMyClass1{internalvoid foo(){Console.WriteLine("hello from foo");}}
Kompiler untuk kode di atas menimbulkan kesalahan bahwa variabel obj tidak ditetapkan yang menandakan bahwa variabel kami memiliki nilai nol atau tidak sama sekali. Kompiler untuk kode di atas menimbulkan kesalahan bahwa variabel obj tidak ditetapkan yang menandakan bahwa variabel kami memiliki nilai nol atau tidak sama sekali.
Kenapa itu terjadi?
NullReferenceException muncul karena kesalahan kami karena tidak memeriksa nilai objek. Kami sering membiarkan nilai objek tidak dicentang dalam pengembangan kode.
Itu juga muncul ketika kita lupa untuk instantiate objek kita. Menggunakan metode, properti, koleksi dll. Yang dapat mengembalikan atau menetapkan nilai nol juga bisa menjadi penyebab pengecualian ini.
Bagaimana itu bisa dihindari?
Ada berbagai cara dan metode untuk menghindari pengecualian terkenal ini:
Pemeriksaan Eksplisit: Kita harus mematuhi tradisi untuk memeriksa objek, properti, metode, array, dan koleksi apakah itu nol. Ini dapat dengan mudah diimplementasikan menggunakan pernyataan kondisional seperti if-else if-else dll.
Penanganan pengecualian: Salah satu cara penting untuk mengelola pengecualian ini. Dengan menggunakan blok coba-tangkap-akhirnya yang sederhana, kita dapat mengontrol pengecualian ini dan juga menyimpan lognya. Ini bisa sangat berguna ketika aplikasi Anda sedang dalam tahap produksi.
Operator kosong: Operator penggabungan nol dan operator kondisional nol juga dapat digunakan dengan praktis saat menetapkan nilai ke objek, variabel, properti, dan bidang.
Debugger: Untuk pengembang, kami memiliki senjata besar untuk debugging bersama kami. Jika kita menghadapi NullReferenceException selama pengembangan wajah kita dapat menggunakan debugger untuk sampai ke sumber pengecualian.
Metode bawaan: Metode sistem seperti GetValueOrDefault (), IsNullOrWhiteSpace () dan IsNullorEmpty () memeriksa nulls dan menetapkan nilai default jika ada nilai nol.
Ada banyak jawaban bagus di sini. Anda juga dapat memeriksa deskripsi yang lebih rinci dengan contoh di blog saya .
Anda pada dasarnya menyalin setengah dari posting blog itu dan menambahkan tidak ada yang baru yang tidak ada jawaban yang ada
CodeCaster
@codecaster Dikatakan menyalin ketika Anda menulis ulang ringkasan dari blog Anda sendiri. Saya tahu tidak ada yang baru dalam jawaban saya dan tidak ada yang baru yang tidak dimiliki oleh jawaban sebelumnya, tetapi saya ingin berkontribusi dengan cara yang lebih canggih dan membiarkan orang lain memahami cara saya memahami. Akan senang bahkan jika itu membantu satu orang. Dengan itikad baik.
Wasim
-4
Jika seseorang mendapatkan pesan ini selama menyimpan atau mengkompilasi build, tutup saja semua file dan kemudian buka file apa saja untuk dikompilasi dan disimpan.
Bagi saya alasannya adalah bahwa saya telah mengganti nama file dan file lama masih terbuka.
Jawaban:
Apa penyebabnya?
Intinya
Anda mencoba menggunakan sesuatu yang ada
null
(atauNothing
di VB.NET). Ini berarti Anda mengaturnyanull
, atau Anda tidak pernah mengaturnya sama sekali.Seperti yang lainnya,
null
akan diedarkan. Jikanull
dalam metode "A", bisa jadi metode "B" meneruskannull
ke metode "A".null
dapat memiliki arti yang berbeda:NullReferenceException
.null
sengaja untuk menunjukkan tidak ada nilai berarti yang tersedia. Perhatikan bahwa C # memiliki konsep datatypes nullable untuk variabel (seperti tabel database dapat memiliki bidang nullable) - Anda dapat menetapkannyanull
untuk menunjukkan tidak ada nilai yang tersimpan di dalamnya, misalnya diint? a = null;
mana tanda tanya menunjukkan bahwa diperbolehkan menyimpan nol dalam variabela
. Anda dapat memeriksa apakah denganif (a.HasValue) {...}
atau denganif (a==null) {...}
. Variabel nullable, sepertia
contoh ini, memungkinkan untuk mengakses nilai melaluia.Value
secara eksplisit, atau sama seperti normal viaa
.Perhatikan bahwa mengaksesnya melalui
a.Value
melemparInvalidOperationException
bukanNullReferenceException
jikaa
itunull
- Anda harus melakukan pemeriksaan sebelumnya, yaitu jika Anda memiliki variabel on-nullable lainint b;
maka Anda harus melakukan tugas sepertiif (a.HasValue) { b = a.Value; }
atau lebih pendekif (a != null) { b = a; }
.Sisa dari artikel ini membahas lebih detail dan menunjukkan kesalahan yang sering dilakukan oleh banyak programmer yang dapat menyebabkan a
NullReferenceException
.Lebih spesifik
The
runtime
melemparkanNullReferenceException
selalu berarti hal yang sama: Anda mencoba untuk menggunakan referensi, dan referensi tidak diinisialisasi (atau itu sekali diinisialisasi, tetapi tidak lagi diinisialisasi).Ini artinya rujukannya
null
, dan Anda tidak dapat mengakses anggota (seperti metode) melaluinull
rujukan. Kasus paling sederhana:Ini akan melempar
NullReferenceException
pada baris kedua karena Anda tidak dapat memanggil metode instanceToUpper()
padastring
referensi yang menunjuknull
.Debugging
Bagaimana Anda menemukan sumber
NullReferenceException
? Selain melihat pengecualian itu sendiri, yang akan dilemparkan tepat di lokasi di mana itu terjadi, aturan umum debugging di Visual Studio berlaku: tempatkan breakpoint strategis dan periksa variabel Anda , baik dengan mengarahkan mouse di atas nama mereka, membuka ( Cepat) Tonton jendela atau gunakan berbagai panel debug seperti Lokal dan Autos.Jika Anda ingin mengetahui di mana referensi itu diatur atau tidak, klik kanan namanya dan pilih "Temukan Semua Referensi". Anda kemudian dapat menempatkan breakpoint di setiap lokasi yang ditemukan dan menjalankan program Anda dengan debugger terpasang. Setiap kali debugger memecah breakpoint seperti itu, Anda perlu menentukan apakah Anda mengharapkan referensi tidak nol, memeriksa variabel, dan memverifikasi bahwa itu menunjuk ke sebuah instance ketika Anda mengharapkannya.
Dengan mengikuti alur program dengan cara ini, Anda dapat menemukan lokasi di mana instance tidak boleh null, dan mengapa tidak diatur dengan benar.
Contohnya
Beberapa skenario umum di mana pengecualian dapat dilemparkan:
Umum
Jika ref1 atau ref2 atau ref3 adalah nol, maka Anda akan mendapatkan
NullReferenceException
. Jika Anda ingin menyelesaikan masalah, maka cari tahu yang mana yang nol dengan menulis ulang ekspresi yang sederhananya:Secara khusus, dalam
HttpContext.Current.User.Identity.Name
,HttpContext.Current
bisa jadi nol, atauUser
properti bisa nol, atauIdentity
properti bisa nol.Tidak langsung
Jika Anda ingin menghindari referensi nol anak (Orang), Anda bisa menginisialisasi dalam konstruktor objek orangtua (Buku).
Inisialisasi Objek Bersarang
Hal yang sama berlaku untuk inisialisasi objek bersarang:
Ini diterjemahkan menjadi
Sementara
new
kata kunci digunakan, itu hanya membuat contoh baruBook
, tetapi bukan contoh baruPerson
, sehinggaAuthor
properti tetapnull
.Inisialisasi Koleksi Bersarang
Koleksi bersarang
Initializers
berperilaku sama:Ini diterjemahkan menjadi
Satu-
new Person
satunya yang membuat instancePerson
, tetapiBooks
koleksinya tetapnull
.Initializer
Sintaks koleksi tidak untuk membuat koleksip1.Books
, itu hanya menerjemahkan kep1.Books.Add(...)
pernyataan.Himpunan
Elemen Array
Array bergerigi
Koleksi / Daftar / Kamus
Variabel Rentang (Tidak Langsung / Ditangguhkan)
Acara
kelas publik Form1 {pelanggan Pelanggan pribadi;
}
Ini dapat dipecahkan dengan mengikuti konvensi ke bidang awalan dengan garis bawah:
ASP.NET Page Life cycle:
Nilai Sesi ASP.NET
ASP.NET MVC model tampilan kosong
Jika pengecualian terjadi ketika mereferensikan properti
@Model
dalamASP.NET MVC View
, Anda perlu memahami bahwaModel
akan diatur dalam metode tindakan Anda, saat Andareturn
melihatnya. Saat Anda mengembalikan model kosong (atau properti model) dari controller Anda, pengecualian terjadi ketika pandangan mengaksesnya:Perintah dan Acara Pembuatan Kontrol WPF
WPF
kontrol dibuat selama panggilan keInitializeComponent
dalam urutan mereka muncul di pohon visual. ANullReferenceException
akan dimunculkan dalam kasus kontrol yang dibuat lebih awal dengan pengendali event, dll., Yang terbakar selamaInitializeComponent
referensi yang membuat kontrol yang dibuat terlambat.Sebagai contoh :
Di sini
comboBox1
dibuat sebelumnyalabel1
. JikacomboBox1_SelectionChanged
upaya untuk mereferensikan `label1, itu belum akan dibuat.Mengubah urutan deklarasi dalam
XAML
(yaitu, daftarlabel1
sebelumnyacomboBox1
, mengabaikan masalah filosofi desain, setidaknya akan menyelesaikan diNullReferenceException
sini.Dipadukan dengan
as
Ini tidak melempar
InvalidCastException
tetapi mengembalikan anull
ketika para pemain gagal (dan kapansomeObject
itu sendiri nol). Jadi sadarilah itu.LINQ
FirstOrDefault()
danSingleOrDefault()
Versi polos
First()
danSingle()
melempar pengecualian ketika tidak ada. Versi "OrDefault" mengembalikan null dalam kasus itu. Jadi sadarilah itu.untuk setiap
foreach
melempar ketika Anda mencoba untuk mengembalikan koleksi nol. Biasanya disebabkan olehnull
hasil tak terduga dari metode yang mengembalikan koleksi.Contoh yang lebih realistis - pilih node dari dokumen XML. Akan melempar jika node tidak ditemukan tetapi debugging awal menunjukkan bahwa semua properti valid:
Cara untuk Dihindari
Secara eksplisit memeriksa
null
dan mengabaikan nilai nol.Jika Anda mengharapkan referensi kadang menjadi nol, Anda dapat memeriksanya
null
sebelum mengakses anggota instance:Periksa secara eksplisit
null
dan berikan nilai default.Metode memanggil Anda berharap untuk kembali contoh dapat kembali
null
, misalnya ketika objek yang dicari tidak dapat ditemukan. Anda dapat memilih untuk mengembalikan nilai default saat ini:Periksa secara eksplisit
null
dari panggilan metode dan berikan pengecualian khusus.Anda juga dapat melempar pengecualian khusus, hanya untuk menangkapnya dalam kode panggilan:
Gunakan
Debug.Assert
jika suatu nilai tidak bolehnull
, untuk menangkap masalah lebih awal dari pengecualian terjadi.Ketika Anda tahu selama pengembangan bahwa suatu metode mungkin bisa, tetapi tidak harus kembali
null
, Anda dapat menggunakannyaDebug.Assert()
untuk memecahkan sesegera mungkin ketika itu terjadi:Meskipun pemeriksaan ini tidak akan berakhir di build rilis Anda , menyebabkannya untuk membuang
NullReferenceException
lagi ketikabook == null
saat runtime dalam mode rilis.Gunakan
GetValueOrDefault()
untuknullable
tipe nilai untuk memberikan nilai default saat itunull
.Gunakan operator penggabungan nol:
??
[C #] atauIf()
[VB].Singkatan untuk memberikan nilai default ketika
null
ditemui:Gunakan operator kondisi nol:
?.
atau?[x]
untuk array (tersedia dalam C # 6 dan VB.NET 14):Ini juga kadang-kadang disebut operator navigasi aman atau Elvis (setelah bentuknya). Jika ekspresi di sisi kiri operator adalah nol, maka sisi kanan tidak akan dievaluasi, dan sebaliknya dikembalikan. Itu artinya kasus-kasus seperti ini:
Jika orang tersebut tidak memiliki judul, ini akan menimbulkan pengecualian karena ia mencoba untuk memanggil
ToUpper
properti dengan nilai nol.Di dalam
C# 5
dan di bawah, ini dapat dijaga dengan:Sekarang variabel judul akan menjadi nol alih-alih melemparkan pengecualian. C # 6 memperkenalkan sintaks yang lebih pendek untuk ini:
Ini akan menghasilkan variabel judul menjadi
null
, dan panggilan keToUpper
tidak dilakukan jikaperson.Title
adanull
.Tentu saja, Anda masih harus memeriksa
title
nol atau menggunakan operator kondisi nol bersama dengan operator penggabungan nol (??
) untuk memberikan nilai default:Demikian juga, untuk array Anda dapat menggunakan
?[i]
sebagai berikut:Ini akan melakukan hal berikut: Jika
myIntArray
bernilai nol, ekspresi mengembalikan nol dan Anda dapat memeriksanya dengan aman. Jika mengandung array, ia akan melakukan hal yang sama seperti:elem = myIntArray[i];
dan mengembalikani<sup>th</sup>
elemen.Gunakan konteks nol (tersedia dalam C # 8):
Diperkenalkan di
C# 8
sana konteks nol dan jenis referensi nullable melakukan analisis statis pada variabel dan memberikan peringatan kompilator jika nilai berpotensi nol atau telah diatur ke nol. Jenis referensi yang dapat dibatalkan memungkinkan jenis untuk secara eksplisit diizinkan menjadi nol.Konteks anotasi yang dapat dibatalkan dan konteks peringatan yang dapat dibatalkan dapat diatur untuk proyek menggunakan
Nullable
elemen dalamcsproj
file Anda . Elemen ini mengonfigurasikan bagaimana kompiler menafsirkan nullability tipe dan peringatan apa yang dihasilkan. Pengaturan yang valid adalah:Tipe referensi nullable dicatat menggunakan sintaksis yang sama dengan tipe nilai nullable: a
?
ditambahkan ke tipe variabel.Teknik khusus untuk debugging dan memperbaiki null deref di iterators
C#
mendukung "blok iterator" (disebut "generator" dalam beberapa bahasa populer lainnya). Pengecualian null dereference bisa sangat sulit untuk debug di blok iterator karena eksekusi yang ditangguhkan:Jika
whatever
hasilnyanull
makaMakeFrob
akan melempar. Sekarang, Anda mungkin berpikir bahwa hal yang benar untuk dilakukan adalah ini:Kenapa ini salah? Karena blok iterator tidak benar - benar berjalan sampai
foreach
! Panggilan untukGetFrobs
hanya mengembalikan objek yang ketika iterasi akan menjalankan blok iterator.Dengan menulis cek nol seperti ini, Anda mencegah null dereference, tetapi Anda memindahkan pengecualian argumen nol ke titik iterasi , bukan ke titik panggilan , dan itu sangat membingungkan untuk debug .
Perbaikan yang benar adalah:
Yaitu, buat metode pembantu pribadi yang memiliki logika blok iterator, dan metode permukaan publik yang melakukan pemeriksaan nol dan mengembalikan iterator. Sekarang ketika
GetFrobs
dipanggil, pemeriksaan nol terjadi segera, dan kemudianGetFrobsForReal
dijalankan ketika urutan diulang.Jika Anda memeriksa sumber referensi untuk
LINQ
Objek, Anda akan melihat bahwa teknik ini digunakan di seluruh. Menulisnya sedikit lebih kikuk, tetapi itu membuat kesalahan nullging debugging jauh lebih mudah. Optimalkan kode Anda untuk kenyamanan penelepon, bukan kenyamanan penulis .Catatan tentang null dereferences in dalam kode tidak aman
C#
memiliki mode "tidak aman" yang, seperti namanya, sangat berbahaya karena mekanisme keselamatan normal yang memberikan keamanan memori dan keamanan tipe tidak ditegakkan. Anda tidak boleh menulis kode yang tidak aman kecuali jika Anda memiliki pemahaman yang mendalam dan mendalam tentang cara kerja memori .Dalam mode tidak aman, Anda harus mengetahui dua fakta penting:
Untuk memahami mengapa hal itu terjadi, ada baiknya untuk memahami bagaimana .NET menghasilkan pengecualian null dereference di tempat pertama. (Detail ini berlaku untuk .NET yang berjalan di Windows; sistem operasi lain menggunakan mekanisme serupa.)
Memori tervirtualisasi dalam
Windows
; setiap proses mendapatkan ruang memori virtual dari banyak "halaman" memori yang dilacak oleh sistem operasi. Setiap halaman memori memiliki flag yang ditetapkan di atasnya yang menentukan bagaimana penggunaannya: membaca dari, ditulis ke, dieksekusi, dan sebagainya. The terendah halaman ditandai sebagai "menghasilkan kesalahan jika pernah digunakan dengan cara apapun".Baik penunjuk nol maupun referensi nol
C#
secara internal direpresentasikan sebagai angka nol, dan setiap upaya untuk merujuknya ke penyimpanan memori yang sesuai menyebabkan sistem operasi menghasilkan kesalahan. The .NET runtime kemudian mendeteksi kesalahan ini dan mengubahnya menjadi pengecualian null dereference.Itu sebabnya dereferencing baik pointer nol dan referensi nol menghasilkan pengecualian yang sama.
Bagaimana dengan poin kedua? Dereferencing setiap pointer tidak valid yang jatuh di halaman terendah memori virtual menyebabkan kesalahan sistem operasi yang sama, dan dengan demikian pengecualian yang sama.
Mengapa ini masuk akal? Nah, misalkan kita memiliki struct yang berisi dua int, dan pointer yang tidak dikelola sama dengan nol. Jika kami mencoba melakukan dereferensi int kedua di struct, ia
CLR
tidak akan mencoba mengakses penyimpanan di lokasi nol; itu akan mengakses penyimpanan di lokasi empat. Tapi secara logis ini adalah dereferensi nol karena kita mendapatkan alamat itu melalui nol.Jika Anda bekerja dengan kode yang tidak aman dan Anda mendapatkan pengecualian null dereference, perlu diketahui bahwa pointer yang menyinggung tidak harus nol. Ini dapat berupa lokasi apa pun di halaman terendah, dan pengecualian ini akan dibuat.
sumber
new Book { Author = { Age = 45 } };
Bagaimana bahkan inisialisasi batin ... Saya tidak bisa memikirkan situasi di mana init dalam akan pernah bekerja, namun itu mengkompilasi dan intellisense bekerja ... Kecuali untuk struct?Pengecualian NullReference - Visual Basic
The
NullReference Exception
untuk Visual Basic tidak berbeda dari yang ada di C # . Bagaimanapun, mereka berdua melaporkan pengecualian yang sama yang didefinisikan dalam .NET Framework yang keduanya gunakan. Penyebab unik untuk Visual Basic jarang terjadi (mungkin hanya satu).Jawaban ini akan menggunakan istilah, sintaks, dan konteks Visual Basic. Contoh yang digunakan berasal dari sejumlah besar pertanyaan Stack Overflow sebelumnya. Ini untuk memaksimalkan relevansi dengan menggunakan jenis situasi yang sering terlihat di posting. Penjelasan lebih banyak juga disediakan bagi mereka yang mungkin membutuhkannya. Contoh yang mirip dengan milik Anda sangat mungkin tercantum di sini.
catatan:
NullReferenceException
(NRE), cara menemukannya, cara memperbaikinya, dan bagaimana cara menghindarinya. NRE dapat disebabkan banyak cara sehingga ini tidak mungkin menjadi satu-satunya pertemuan Anda.Arti Dasar
Pesan "Objek tidak disetel ke instance Objek" berarti Anda mencoba menggunakan objek yang belum diinisialisasi. Ini bermuara pada salah satu dari ini:
Menemukan Penyebabnya
Karena masalahnya adalah referensi objek
Nothing
, jawabannya adalah memeriksa mereka untuk mengetahui yang mana. Kemudian tentukan mengapa itu tidak diinisialisasi. Pegang mouse di atas berbagai variabel dan Visual Studio (VS) akan menunjukkan nilainya - biang keladinyaNothing
.Anda juga harus menghapus blok Coba / Tangkap dari kode yang relevan, terutama yang tidak ada di blok Tangkap. Ini akan menyebabkan kode Anda mogok ketika mencoba menggunakan objek yang
Nothing
. Ini yang Anda inginkan karena akan mengidentifikasi lokasi pasti masalah, dan memungkinkan Anda mengidentifikasi objek yang menyebabkannya.A
MsgBox
di Catch yang menampilkanError while...
akan sedikit membantu. Metode ini juga mengarah ke pertanyaan Stack Overflow yang sangat buruk , karena Anda tidak dapat mendeskripsikan pengecualian aktual, objek yang terlibat, atau bahkan baris kode tempat terjadinya.Anda juga dapat menggunakan
Locals Window
( Debug -> Windows -> Locals ) untuk memeriksa objek Anda.Setelah Anda tahu apa dan di mana masalahnya, biasanya cukup mudah untuk memperbaiki dan lebih cepat daripada mengirim pertanyaan baru.
Lihat juga:
Contoh dan Solusi
Objek Kelas / Membuat Instance
Masalahnya adalah bahwa
Dim
itu tidak membuat objek CashRegister ; itu hanya mendeklarasikan variabel bernamareg
Tipe itu. Mendeklarasikan variabel objek dan membuat instance adalah dua hal yang berbeda.Obat
The
New
Operator sering dapat digunakan untuk membuat contoh ketika Anda menyatakan hal itu:Saat yang tepat untuk membuat instance nanti:
Catatan: Jangan gunakan
Dim
lagi dalam prosedur, termasuk konstruktor (Sub New
):Ini akan membuat variabel lokal
reg
,, yang hanya ada dalam konteks (sub). Thereg
variabel dengan tingkat modulScope
yang akan Anda gunakan sisa-sisa di tempat lainNothing
.Untuk menjadi jelas,
Dim
(atauPrivate
) hanya mendeklarasikan variabel dan variabelnyaType
. The Lingkup variabel - apakah itu ada untuk seluruh modul / kelas atau lokal untuk prosedur - ditentukan oleh di mana ia dideklarasikan.Private | Friend | Public
mendefinisikan tingkat akses, bukan Lingkup .Untuk informasi lebih lanjut, lihat:
Array
Array juga harus dipakai:
Array ini hanya dideklarasikan, tidak dibuat. Ada beberapa cara untuk menginisialisasi array:
Catatan: Dimulai dengan VS 2010, ketika menginisialisasi array lokal menggunakan literal dan
Option Infer
, elemenAs <Type>
danNew
opsional:Tipe data dan ukuran array disimpulkan dari data yang ditugaskan. Tingkat deklarasi kelas / Modul masih memerlukan
As <Type>
denganOption Strict
:Contoh: Array objek kelas
Array telah dibuat, tetapi
Foo
objek di dalamnya belum.Obat
Menggunakan
List(Of T)
akan membuatnya sangat sulit untuk memiliki elemen tanpa objek yang valid:Untuk informasi lebih lanjut, lihat:
Daftar dan Koleksi
Koleksi .NET (yang ada banyak varietas - Daftar, Kamus, dll.) Juga harus dipakai atau dibuat.
Anda mendapatkan pengecualian yang sama karena alasan yang sama -
myList
hanya dideklarasikan, tetapi tidak ada instance yang dibuat. Obatnya sama:Pengawasan umum adalah kelas yang menggunakan koleksi
Type
:Setiap prosedur akan menghasilkan NRE, karena
barList
hanya dideklarasikan, tidak dipakai. Menciptakan instanceFoo
tidak akan juga membuat instance internalbarList
. Mungkin maksud untuk melakukan ini di konstruktor:Seperti sebelumnya, ini tidak benar:
Untuk informasi lebih lanjut, lihat
List(Of T)
Kelas .Objek Penyedia Data
Bekerja dengan database hadiah banyak kesempatan untuk NullReference karena akan ada banyak benda (
Command
,Connection
,Transaction
,Dataset
,DataTable
,DataRows
....) digunakan sekaligus. Catatan: Tidak masalah penyedia data mana yang Anda gunakan - MySQL, SQL Server, OleDB, dll - konsep sama.Contoh 1
Seperti sebelumnya,
ds
objek Dataset dideklarasikan, tetapi sebuah instance tidak pernah dibuat. TheDataAdapter
akan mengisi yang adaDataSet
, tidak membuat satu. Dalam hal ini, karenads
merupakan variabel lokal, IDE memperingatkan Anda bahwa ini mungkin terjadi:Ketika dideklarasikan sebagai variabel tingkat modul / kelas, seperti yang terlihat dengan kasus
con
, kompiler tidak dapat mengetahui apakah objek itu dibuat oleh prosedur hulu. Jangan abaikan peringatan.Obat
Contoh 2
Sebuah kesalahan ketik adalah masalah di sini:
Employees
vsEmployee
. Tidak adaDataTable
nama "Karyawan" yang dibuat, jadi suatuNullReferenceException
hasil mencoba mengaksesnya. Masalah potensial lainnya adalah dengan asumsi akan adaItems
yang mungkin tidak terjadi ketika SQL menyertakan klausa WHERE.Obat
Karena ini menggunakan satu tabel, penggunaan
Tables(0)
akan menghindari kesalahan ejaan. MemeriksaRows.Count
juga dapat membantu:Fill
adalah fungsi mengembalikan jumlah yangRows
terpengaruh yang juga dapat diuji:Contoh 3
The
DataAdapter
akan memberikanTableNames
seperti yang ditunjukkan pada contoh sebelumnya, tetapi tidak nama parse dari SQL atau database meja. Hasil dari,ds.Tables("TICKET_RESERVATION")
referensi tabel tidak ada.The Remedy adalah sama, referensi tabel dengan indeks:
Lihat juga Kelas DataTable .
Jalur Objek / Bersarang
Kode hanya menguji
Items
sementara keduanyamyFoo
danBar
mungkin juga Tidak Ada. The obat adalah untuk menguji seluruh rantai atau jalur objek satu per satu:AndAlso
penting. Tes selanjutnya tidak akan dilakukan setelahFalse
kondisi pertama ditemui. Ini memungkinkan kode untuk dengan aman 'menelusuri' ke objek satu tingkat di satu waktu, mengevaluasimyFoo.Bar
hanya setelah (dan jika)myFoo
ditentukan valid. Rantai atau lintasan objek bisa menjadi cukup lama ketika mengkode objek kompleks:Tidak mungkin untuk merujuk apa pun 'hilir' dari suatu
null
objek. Ini juga berlaku untuk kontrol:Di sini,
myWebBrowser
atauDocument
bisa jadi Tidak ada atauformfld1
elemen mungkin tidak ada.Kontrol UI
Antara lain, kode ini tidak mengantisipasi bahwa pengguna mungkin tidak memilih sesuatu dalam satu atau lebih kontrol UI.
ListBox1.SelectedItem
mungkinNothing
, jadiListBox1.SelectedItem.ToString
akan menghasilkan NRE.Obat
Validasi data sebelum menggunakannya (juga gunakan
Option Strict
dan parameter SQL):Atau, Anda dapat menggunakan
(ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Bentuk Visual Basic
Ini adalah cara yang cukup umum untuk mendapatkan NRE. Dalam C #, tergantung pada bagaimana dikodekan, IDE akan melaporkan yang
Controls
tidak ada dalam konteks saat ini, atau "tidak dapat merujuk anggota non-statis". Jadi, sampai batas tertentu, ini hanya situasi VB. Ini juga kompleks karena dapat mengakibatkan kegagalan kaskade.Array dan koleksi tidak dapat diinisialisasi dengan cara ini. Kode inisialisasi ini akan berjalan sebelum konstruktor membuat
Form
atauControls
. Hasil dari:somevar
tugas akan menghasilkan NRE segera karena ada tidak memiliki.Text
propertiMerujuk elemen array nanti akan menghasilkan NRE. Jika Anda melakukan ini
Form_Load
, karena bug aneh, IDE tidak dapat melaporkan pengecualian ketika itu terjadi. Pengecualian akan muncul nanti ketika kode Anda mencoba menggunakan array. "Pengecualian sunyi" ini dirinci dalam pos ini . Untuk tujuan kami, kuncinya adalah bahwa ketika sesuatu bencana terjadi saat membuat formulir (Sub New
atauForm Load
peristiwa), pengecualian mungkin tidak dilaporkan, kode keluar dari prosedur dan hanya menampilkan formulir.Karena tidak ada kode lain di Anda
Sub New
atauForm Load
acara akan berjalan setelah NRE tersebut, banyak hal lain dapat dibiarkan uninitialized.Catatan ini berlaku untuk setiap dan semua kontrol dan referensi komponen membuat ini ilegal di mana mereka berada:
Obat Parsial
Sangat mengherankan bahwa VB tidak memberikan peringatan, tetapi obatnya adalah dengan mendeklarasikan kontainer pada level form, tetapi menginisialisasi mereka dalam form load event handler ketika kontrol benar-benar ada. Ini dapat dilakukan
Sub New
selama kode Anda setelahInitializeComponent
panggilan:Kode array mungkin belum keluar dari hutan. Kontrol apa pun yang ada dalam kontrol wadah (seperti a
GroupBox
atauPanel
) tidak akan ditemukan diMe.Controls
; mereka akan berada di koleksi Kontrol Panel atau GroupBox itu. Kontrol juga tidak akan dikembalikan ketika nama kontrol salah eja ("TeStBox2"
). Dalam kasus seperti itu,Nothing
sekali lagi akan disimpan dalam elemen array tersebut dan NRE akan dihasilkan ketika Anda mencoba untuk referensi itu.Ini seharusnya mudah ditemukan sekarang setelah Anda tahu apa yang Anda cari:![VS menunjukkan kesalahan cara Anda](https://i.stack.imgur.com/5ndSA.jpg)
"Button2" berada di a
Panel
Obat
Daripada referensi tidak langsung dengan nama menggunakan
Controls
koleksi formulir , gunakan referensi kontrol:Tidak Mengembalikan Fungsi
Ini adalah kasus di mana IDE akan memperingatkan Anda bahwa ' tidak semua jalur mengembalikan nilai dan
NullReferenceException
hasil dapat '. Anda dapat menekan peringatan, dengan menggantiExit Function
denganReturn Nothing
, tetapi itu tidak memecahkan masalah. Apa pun yang mencoba menggunakan pengembalian ketikasomeCondition = False
akan menghasilkan NRE:Obat
Ganti
Exit Function
fungsi denganReturn bList
. Mengembalikan kosongList
tidak sama dengan mengembalikanNothing
. Jika ada kemungkinan objek yang dikembalikan dapatNothing
, uji sebelum menggunakannya:Coba / Tangkap yang Diimplementasikan dengan Buruk
Try / Catch yang diimplementasikan dengan buruk dapat menyembunyikan di mana masalahnya dan menghasilkan yang baru:
Ini adalah kasus objek tidak dibuat seperti yang diharapkan, tetapi juga menunjukkan manfaat kontra dari yang kosong
Catch
.Ada koma tambahan di SQL (setelah 'alamat surat') yang menghasilkan pengecualian di
.ExecuteReader
. SetelahCatch
tidak melakukan apa-apa,Finally
cobalah untuk melakukan pembersihan, tetapi karena Anda tidak dapat objekClose
nolDataReader
,NullReferenceException
hasil baru .Catch
Blok kosong adalah taman bermain iblis. OP ini bingung mengapa dia mendapatkan NRE diFinally
blok. Dalam situasi lain, sebuah kekosonganCatch
dapat mengakibatkan sesuatu yang lebih jauh ke hilir menjadi berantakan dan menyebabkan Anda menghabiskan waktu melihat hal-hal yang salah di tempat yang salah untuk masalah tersebut. ("Pengecualian sunyi" yang dijelaskan di atas memberikan nilai hiburan yang sama.)Obat
Jangan gunakan blok Coba / Tangkap kosong - biarkan kode macet sehingga Anda dapat a) mengidentifikasi penyebab b) mengidentifikasi lokasi dan c) menerapkan obat yang tepat. Blok Coba / Tangkap tidak dimaksudkan untuk menyembunyikan pengecualian dari orang yang memiliki kualifikasi unik untuk memperbaikinya - pengembang.
DBNull tidak sama dengan Tidak Ada
The
IsDBNull
Fungsi ini digunakan untuk menguji apakah nilai samaSystem.DBNull
: Dari MSDN:Obat
Seperti sebelumnya, Anda dapat menguji Tidak Ada, kemudian untuk nilai tertentu:
Contoh 2
FirstOrDefault
mengembalikan item pertama atau nilai default, yangNothing
untuk tipe referensi dan tidak pernahDBNull
:Kontrol
Jika sebuah
CheckBox
denganchkName
tidak dapat ditemukan (atau ada di aGroupBox
), makachk
akan menjadi Apa-apa dan berusaha untuk referensi properti apa pun akan menghasilkan pengecualian.Obat
DataGridView
DGV memiliki beberapa kebiasaan yang dilihat secara berkala:
Jika
dgvBooks
sudahAutoGenerateColumns = True
, itu akan membuat kolom, tetapi tidak menamai mereka, jadi kode di atas gagal ketika referensi mereka dengan nama.Obat
Beri nama kolom secara manual, atau referensi berdasarkan indeks:
Contoh 2 - Waspadalah terhadap NewRow
Ketika Anda
DataGridView
memilikiAllowUserToAddRows
asTrue
(default),Cells
baris kosong / baru di bagian bawah semuanya akan berisiNothing
. Sebagian besar upaya untuk menggunakan konten (misalnya,ToString
) akan menghasilkan NRE.Obat
Gunakan
For/Each
perulangan dan ujiIsNewRow
properti untuk menentukan apakah itu baris terakhir. Ini berfungsi baikAllowUserToAddRows
benar atau tidak:Jika Anda menggunakan
For n
loop, modifikasi jumlah baris atau gunakanExit For
kapanIsNewRow
benar.Pengaturan Saya (StringCollection)
Dalam keadaan tertentu, mencoba menggunakan item
My.Settings
yangStringCollection
dapat menghasilkan NullReference saat pertama kali Anda menggunakannya. Solusinya sama, tetapi tidak sejelas itu. Mempertimbangkan:Karena VB mengelola Pengaturan untuk Anda, masuk akal untuk mengharapkannya untuk menginisialisasi koleksi. Itu akan, tetapi hanya jika Anda sebelumnya telah menambahkan entri awal ke koleksi (di Editor pengaturan). Karena koleksi (tampaknya) diinisialisasi ketika item ditambahkan, ia tetap
Nothing
ketika tidak ada item dalam editor Pengaturan untuk ditambahkan.Obat
Inisialisasi koleksi pengaturan di
Load
pengendali acara formulir , jika / ketika dibutuhkan:Biasanya,
Settings
koleksi hanya perlu diinisialisasi saat pertama kali aplikasi dijalankan. Obat alternatif adalah menambahkan nilai awal ke koleksi Anda di Proyek -> Pengaturan | FooBars , simpan proyek, lalu hapus nilai palsu.Poin-Poin Utama
Anda mungkin lupa
New
operatornya.atau
Sesuatu yang Anda asumsikan akan tampil sempurna untuk mengembalikan objek yang diinisialisasi ke kode Anda, tidak.
Jangan abaikan peringatan kompiler (selalu) dan gunakan
Option Strict On
(selalu).Pengecualian NullReference MSDN
sumber
Skenario lain adalah ketika Anda melemparkan objek nol ke dalam tipe nilai . Misalnya, kode di bawah ini:
Ini akan melempar
NullReferenceException
pada pemain. Tampaknya cukup jelas dalam sampel di atas, tetapi ini dapat terjadi dalam skenario rumit yang lebih "mengikat" di mana objek null telah dikembalikan dari beberapa kode yang tidak Anda miliki, dan para pemain misalnya dihasilkan oleh beberapa sistem otomatis.Salah satu contohnya adalah fragmen pengikat ASP.NET sederhana ini dengan kontrol Kalender:
Di sini,
SelectedDate
sebenarnya adalah properti -DateTime
tipe - dariCalendar
tipe Kontrol Web, dan pengikatan dengan sempurna dapat mengembalikan sesuatu yang nol. ASP.NET Generator implisit akan membuat sepotong kode yang akan setara dengan kode pemain di atas. Dan ini akan meningkatkanNullReferenceException
yang cukup sulit dikenali, karena terletak pada kode ASP.NET yang dihasilkan yang mengkompilasi ...sumber
DateTime x = (DateTime) o as DateTime? ?? defaultValue;
Ini berarti bahwa variabel yang dipermasalahkan tidak menunjuk apa-apa. Saya dapat menghasilkan ini seperti ini:
Itu akan membuang kesalahan karena sementara saya sudah mendeklarasikan variabel "
connection
", itu tidak menunjuk ke apa pun. Ketika saya mencoba memanggil anggota "Open
", tidak ada referensi untuk diselesaikan, dan itu akan menimbulkan kesalahan.Untuk menghindari kesalahan ini:
object == null
.Alat Resharper JetBrains akan mengidentifikasi setiap tempat dalam kode Anda yang memiliki kemungkinan kesalahan referensi nol, memungkinkan Anda untuk memasukkan cek nol. Kesalahan ini adalah sumber bug nomor satu, IMHO.
sumber
Ini berarti kode Anda menggunakan variabel referensi objek yang disetel ke nol (artinya tidak mereferensikan instance objek aktual).
Untuk mencegah kesalahan, objek yang bisa null harus diuji untuk null sebelum digunakan.
sumber
Perlu diketahui bahwa terlepas dari skenario, penyebabnya selalu sama di .NET:
sumber
Contoh pengecualian ini yang dilemparkan adalah: Ketika Anda mencoba untuk memeriksa sesuatu, itu adalah nol.
Sebagai contoh:
The .NET runtime akan melempar NullReferenceException ketika Anda mencoba untuk melakukan suatu tindakan pada sesuatu yang belum dipakai misalnya kode di atas.
Dibandingkan dengan ArgumentNullException yang biasanya dilemparkan sebagai tindakan defensif jika suatu metode mengharapkan bahwa apa yang diteruskan ke sana bukan nol.
Informasi lebih lanjut ada di C # NullReferenceException dan Null Parameter .
sumber
Pembaruan C # 8.0, 2019: Jenis referensi tidak dapat dibatalkan
C # 8.0 memperkenalkan jenis referensi yang dapat dibatalkan dan jenis referensi yang tidak dapat dibatalkan . Jadi hanya jenis referensi yang dapat dibatalkan yang harus diperiksa untuk menghindari NullReferenceException .
Jika Anda belum menginisialisasi tipe referensi, dan Anda ingin mengatur atau membaca salah satu propertinya, ia akan melempar NullReferenceException .
Contoh:
Anda bisa menghindari ini dengan memeriksa apakah variabelnya bukan nol:
Untuk memahami sepenuhnya mengapa NullReferenceException dilemparkan, penting untuk mengetahui perbedaan antara tipe nilai dan [tipe referensi] [3].
Jadi, jika Anda berurusan dengan tipe nilai , NullReferenceExceptions tidak dapat terjadi. Meskipun Anda harus tetap waspada ketika berhadapan dengan jenis referensi !
Hanya tipe referensi, seperti yang disarankan namanya, dapat menahan referensi atau menunjukkan apa-apa (atau 'nol'). Sedangkan tipe nilai selalu mengandung nilai.
Jenis referensi (yang ini harus diperiksa):
Jenis nilai (Anda dapat mengabaikannya):
sumber
Kasus lain yang
NullReferenceExceptions
dapat terjadi adalah penggunaan (salah)as
operator :Di sini,
Book
danCar
merupakan tipe yang tidak kompatibel; aCar
tidak dapat dikonversi / dilemparkan ke aBook
. Ketika para pemeran ini gagal,as
kembalinull
. Penggunaanmybook
setelah ini menyebabkan aNullReferenceException
.Secara umum, Anda harus menggunakan gips atau
as
, sebagai berikut:Jika Anda mengharapkan konversi tipe selalu berhasil (mis. Anda tahu objek apa yang harus ada sebelumnya), maka Anda harus menggunakan pemeran:
Jika Anda tidak yakin dengan jenisnya, tetapi Anda ingin mencoba menggunakannya sebagai jenis tertentu, maka gunakan
as
:sumber
Anda menggunakan objek yang berisi referensi nilai nol. Jadi itu memberikan pengecualian nol. Dalam contoh nilai string adalah nol dan ketika memeriksa panjangnya, pengecualian terjadi.
Contoh:
Kesalahan pengecualian adalah:
sumber
Sementara apa yang menyebabkan NullReferenceExceptions dan pendekatan untuk menghindari / memperbaiki pengecualian tersebut telah diatasi dalam jawaban lain, apa yang belum dipelajari oleh banyak programmer adalah bagaimana cara secara independen men - debug pengecualian seperti itu selama pengembangan.
Dalam Visual Studio ini biasanya mudah berkat Debugger Visual Studio .
Pertama, pastikan bahwa kesalahan yang benar akan ditangkap - lihat Bagaimana cara saya membolehkan melanggar pada 'System.NullReferenceException' di VS2010? Catatan 1
Kemudian Mulai dengan Debugging (F5) atau Lampirkan [Debugger VS] untuk Menjalankan Proses . Kadang-kadang mungkin berguna untuk digunakan
Debugger.Break
, yang akan mendorong untuk meluncurkan debugger.Sekarang, ketika NullReferenceException dilempar (atau tidak ditangani) debugger akan berhenti (ingat aturan yang ditetapkan di atas?) Pada baris di mana pengecualian terjadi. Terkadang kesalahan akan mudah dikenali.
Misalnya, pada baris berikut, satu-satunya kode yang dapat menyebabkan pengecualian adalah jika
myString
bernilai nol. Ini dapat diverifikasi dengan melihat Jendela Tonton atau menjalankan ekspresi di Jendela Segera .Dalam kasus yang lebih maju, seperti berikut ini, Anda harus menggunakan salah satu teknik di atas (Tonton atau Segera Windows) untuk memeriksa ekspresi untuk menentukan apakah
str1
itu nol atau jikastr2
itu nol.Setelah di mana pengecualian adalah lemparan telah ditemukan, biasanya sepele untuk mundur alasan untuk mencari tahu di mana nilai null itu [salah] diperkenalkan -
Luangkan waktu yang dibutuhkan untuk memahami penyebab pengecualian. Periksa untuk ekspresi nol. Periksa ekspresi sebelumnya yang bisa menghasilkan ekspresi nol seperti itu. Tambahkan breakpoints dan melangkah melalui program yang sesuai.Gunakan debugger.
1 Jika Break on Throws terlalu agresif dan debugger berhenti pada NPE di pustaka .NET atau pihak ketiga, Break on User-Unhandled dapat digunakan untuk membatasi pengecualian yang tertangkap. Selain itu, VS2012 memperkenalkan Just My Code yang saya sarankan aktifkan juga.
sumber
Simon Mourier memberi contoh ini :
di mana konversi unboxing (dilemparkan) dari
object
(atau dari salah satu kelasSystem.ValueType
atauSystem.Enum
, atau dari tipe antarmuka) ke tipe nilai (selainNullable<>
) dengan sendirinya memberikanNullReferenceException
.Di arah lain, sebuah tinju konversi dari suatu
Nullable<>
yang memilikiHasValue
samafalse
untuk tipe referensi, dapat memberikannull
referensi yang kemudian dapat kemudian menyebabkanNullReferenceException
. Contoh klasik adalah:Terkadang tinju terjadi dengan cara lain. Misalnya dengan metode ekstensi non-generik ini:
kode berikut akan bermasalah:
Kasus-kasus ini muncul karena aturan khusus yang digunakan runtime ketika
Nullable<>
instance tinju .sumber
Menambahkan kasus ketika nama kelas untuk entitas yang digunakan dalam kerangka entitas sama dengan nama kelas untuk file kode-belakang formulir web.
Misalkan Anda memiliki formulir web Contact.aspx yang kelas codebehindnya adalah Kontak dan Anda memiliki nama entitas Kontak.
Kemudian kode berikut akan melempar NullReferenceException ketika Anda memanggil context.SaveChanges ()
Demi kelengkapan kelas DataContext
dan kelas entitas kontak. Kadang-kadang kelas entitas adalah kelas parsial sehingga Anda dapat memperluas mereka di file lain juga.
Kesalahan terjadi ketika kedua entitas dan kelas codebehind berada di namespace yang sama. Untuk memperbaikinya, ganti nama kelas entitas atau kelas kode kode untuk Contact.aspx.
Alasan saya masih belum yakin tentang alasannya. Tetapi setiap kali kelas entitas akan memperpanjang System.Web.UI.Page kesalahan ini terjadi.
Untuk diskusi, lihat NullReferenceException di DbContext.saveChanges ()
sumber
Kasus umum lain di mana orang mungkin menerima pengecualian ini melibatkan kelas mengejek selama pengujian unit. Terlepas dari kerangka mengejek yang digunakan, Anda harus memastikan bahwa semua level hirarki kelas yang sesuai diejek dengan benar. Secara khusus, semua properti dari
HttpContext
yang dirujuk oleh kode yang diuji harus diejek.Lihat " NullReferenceException yang dilemparkan ketika menguji custom AuthorizationAttribute " untuk contoh yang agak bertele-tele.
sumber
Saya memiliki perspektif berbeda untuk menjawab ini. Jawaban semacam ini "apa lagi yang bisa saya lakukan untuk menghindarinya? "
Ketika bekerja di berbagai lapisan , misalnya dalam aplikasi MVC, pengontrol membutuhkan layanan untuk memanggil operasi bisnis. Dalam skenario seperti itu, Dependency Injection Container dapat digunakan untuk menginisialisasi layanan untuk menghindari NullReferenceException . Jadi itu berarti Anda tidak perlu khawatir tentang memeriksa null dan cukup memanggil layanan dari controller seolah-olah mereka akan selalu tersedia (dan diinisialisasi) baik sebagai singleton atau prototipe.
sumber
Untuk masalah "apa yang harus saya lakukan" , ada banyak jawaban.
Cara yang lebih "formal" untuk mencegah kondisi kesalahan seperti itu saat mengembangkan adalah menerapkan desain dengan kontrak dalam kode Anda. Ini berarti Anda perlu mengatur kelas invarian , dan / atau bahkan fungsi / metode prasyarat dan postkondisi pada sistem Anda, sambil mengembangkan.
Singkatnya, invarian kelas memastikan bahwa akan ada beberapa kendala di kelas Anda yang tidak akan dilanggar dalam penggunaan normal (dan oleh karena itu, kelas tidak akan mendapatkan dalam keadaan tidak konsisten). Prasyarat berarti bahwa data yang diberikan sebagai input ke fungsi / metode harus mengikuti beberapa batasan yang ditetapkan dan tidak pernah melanggarnya, dan postkondisi berarti bahwa output fungsi / metode harus mengikuti batasan yang ditetapkan lagi tanpa pernah melanggarnya. Kondisi kontrak tidak boleh dilanggar selama pelaksanaan program bebas bug, oleh karena itu desain berdasarkan kontrak diperiksa dalam praktiknya dalam mode debug, sementara dinonaktifkan dalam rilis , untuk memaksimalkan kinerja sistem yang dikembangkan.
Dengan cara ini, Anda dapat menghindari
NullReferenceException
kasus-kasus yang merupakan hasil pelanggaran terhadap batasan yang ditetapkan. Misalnya, jika Anda menggunakan properti objekX
di kelas dan kemudian mencoba memanggil salah satu metode danX
memiliki nilai nol, maka ini akan mengarah keNullReferenceException
:Tetapi jika Anda menetapkan "properti X tidak boleh memiliki nilai nol" sebagai prasyarat metode, maka Anda dapat mencegah skenario yang dijelaskan sebelumnya:
Untuk alasan ini, proyek Kontrak Kode ada untuk aplikasi .NET.
Atau, desain berdasarkan kontrak dapat diterapkan dengan menggunakan asersi .
UPDATE: Perlu disebutkan bahwa istilah ini diciptakan oleh Bertrand Meyer sehubungan dengan desainnya bahasa pemrograman Eiffel .
sumber
A
NullReferenceException
dilemparkan ketika kita mencoba mengakses Properti dari objek nol atau ketika nilai string menjadi kosong dan kita mencoba mengakses metode string.Sebagai contoh:
Ketika metode string dari string kosong diakses:
Ketika properti objek null diakses:
sumber
String.Empty.ToLower()
tidak akan melempar pengecualian referensi nol. Ini mewakili string aktual, meskipun yang kosong (yaitu""
). Karena ini memiliki objek untuk dipanggilToLower()
, tidak masuk akal untuk melempar pengecualian referensi nol di sana.TL; DR: Coba gunakan
Html.Partial
sebagai gantiRenderpage
Saya mendapatkan
Object reference not set to an instance of an object
ketika saya mencoba menyajikan Tampilan dalam Tampilan dengan mengirimkannya Model, seperti ini:Debugging menunjukkan model itu Null di dalam MyOtherView. Sampai saya mengubahnya menjadi:
Dan itu berhasil.
Selain itu, alasan saya tidak harus
Html.Partial
memulainya adalah karena Visual Studio kadang-kadang melempar garis berlekuk-galat di bawahHtml.Partial
jika itu di dalamforeach
loop yang dibangun secara berbeda , meskipun itu sebenarnya bukan kesalahan:Tapi saya bisa menjalankan aplikasi tanpa masalah dengan "kesalahan" ini. Saya dapat menyingkirkan kesalahan dengan mengubah struktur
foreach
loop agar terlihat seperti ini:Meskipun saya merasa itu karena Visual Studio salah membaca tanda kurung dan kurung.
sumber
Html.Partial
, bukan@Html.Partial
Null
), jadi saya tahu kesalahannya adalah bagaimana saya mengirim Model.Apa yang bisa kamu lakukan?
Ada banyak jawaban bagus di sini yang menjelaskan referensi nol dan bagaimana men-debug-nya. Tetapi ada sangat sedikit tentang bagaimana mencegah masalah atau setidaknya membuatnya lebih mudah untuk ditangkap.
Periksa argumen
Sebagai contoh, metode dapat memeriksa argumen yang berbeda untuk melihat apakah mereka nol dan melempar
ArgumentNullException
, pengecualian yang jelas dibuat untuk tujuan yang tepat ini.Konstruktor untuk
ArgumentNullException
even mengambil nama parameter dan pesan sebagai argumen sehingga Anda dapat memberi tahu pengembang apa masalahnya.Gunakan Alat
Ada juga beberapa perpustakaan yang dapat membantu. "Resharper" misalnya dapat memberi Anda peringatan saat Anda menulis kode, terutama jika Anda menggunakan atributnya: NotNullAttribute
Ada "Kontrak Kode Microsoft" di mana Anda menggunakan sintaksis seperti
Contract.Requires(obj != null)
yang memberi Anda runtime dan kompilasi memeriksa: Memperkenalkan Kontrak Kode .Ada juga "PostSharp" yang akan memungkinkan Anda untuk hanya menggunakan atribut seperti ini:
Dengan melakukan itu dan menjadikan PostSharp bagian dari proses build Anda
obj
akan diperiksa nol pada saat runtime. Lihat: cek kosong PostSharpSolusi Kode Biasa
Atau Anda selalu bisa mengkode pendekatan Anda sendiri menggunakan kode lama polos. Misalnya di sini adalah struct yang dapat Anda gunakan untuk menangkap referensi nol. Ini dimodelkan setelah konsep yang sama dengan
Nullable<T>
:Anda akan menggunakan sangat mirip dengan cara yang sama Anda akan gunakan
Nullable<T>
, kecuali dengan tujuan mencapai yang sebaliknya - untuk tidak mengizinkannull
. Berikut ini beberapa contohnya:NotNull<T>
secara implisit dilemparkan ke dan dariT
sehingga Anda dapat menggunakannya di mana saja Anda membutuhkannya. Misalnya, Anda bisa meneruskanPerson
objek ke metode yang mengambilNotNull<Person>
:Seperti yang Anda lihat di atas sebagai nullable, Anda akan mengakses nilai yang mendasarinya melalui
Value
properti. Atau, Anda dapat menggunakan gips eksplisit atau implisit, Anda dapat melihat contoh dengan nilai pengembalian di bawah:Atau Anda bahkan dapat menggunakannya ketika metode baru saja kembali
T
(dalam hal iniPerson
) dengan melakukan gips. Misalnya, kode berikut hanya akan seperti kode di atas:Gabungkan dengan Extension
Kombinasikan
NotNull<T>
dengan metode ekstensi dan Anda dapat membahas lebih banyak situasi. Berikut adalah contoh tampilan metode ekstensi:Dan ini adalah contoh bagaimana itu bisa digunakan:
GitHub
Untuk referensi Anda, saya membuat kode di atas tersedia di GitHub, Anda dapat menemukannya di:
https://github.com/luisperezphd/NotNull
Fitur Bahasa Terkait
C # 6.0 memperkenalkan "operator null-kondisional" yang sedikit membantu. Dengan fitur ini, Anda dapat mereferensikan objek bersarang dan jika salah satunya adalah
null
keseluruhan ekspresi yang dikembalikannull
.Ini mengurangi jumlah cek nol yang harus Anda lakukan dalam beberapa kasus. Sintaksnya adalah meletakkan tanda tanya sebelum setiap titik. Ambil kode berikut sebagai contoh:
Bayangkan itu
country
adalah objek tipeCountry
yang memiliki properti yang disebutState
dan sebagainya. Jikacountry
,State
,County
, atauCity
yangnull
kemudianaddress will be
nol. Therefore you only have to check whether
alamatis
null`.Ini fitur hebat, tetapi memberi Anda lebih sedikit informasi. Itu tidak membuatnya jelas yang mana dari 4 adalah nol.
Built-in seperti Nullable?
C # memiliki singkatan yang bagus untuk
Nullable<T>
, Anda dapat membuat sesuatu nullable dengan meletakkan tanda tanya setelah tipe seperti ituint?
.Akan lebih baik jika C # memiliki sesuatu seperti
NotNull<T>
struct di atas dan memiliki singkatan yang sama, mungkin tanda seru sehingga Anda bisa menulis sesuatu seperti (!):public void WriteName(Person! person)
.sumber
Menariknya, tidak ada jawaban di halaman ini yang menyebutkan dua sisi tepi, harap tidak ada yang keberatan jika saya menambahkannya:
Kasus tepi # 1: akses bersamaan ke Kamus
Kamus umum di .NET tidak aman untuk thread dan kadang - kadang mereka melempar
NullReference
atau bahkan (lebih sering) aKeyNotFoundException
ketika Anda mencoba mengakses kunci dari dua utas secara bersamaan. Pengecualian cukup menyesatkan dalam kasus ini.Kasing tepi # 2: kode tidak aman
Jika
NullReferenceException
dilemparkan olehunsafe
kode, Anda mungkin melihat variabel pointer Anda, dan memeriksanyaIntPtr.Zero
atau sesuatu. Yang merupakan hal yang sama ("pengecualian pointer nol"), tetapi dalam kode yang tidak aman, variabel sering dilemparkan ke tipe-nilai / array, dll., Dan Anda membenturkan kepala ke dinding, bertanya-tanya bagaimana tipe-nilai dapat membuang ini pengecualian.(Alasan lain untuk tidak menggunakan kode tidak aman kecuali Anda memerlukannya, by the way)
sumber
null
dengan caranya?Anda dapat memperbaiki NullReferenceException dengan cara yang bersih menggunakan Null-conditional Operator di c # 6 dan menulis lebih sedikit kode untuk menangani cek nol.
Ini digunakan untuk menguji nol sebelum melakukan operasi akses anggota (?) Atau indeks (? [).
Contoh
setara dengan:
Hasilnya adalah bahwa nama akan menjadi nol ketika p adalah nol atau ketika p. Pasangan adalah nol.
Jika tidak, nama variabel akan diberi nilai p.Spouse.FirstName.
Untuk lebih jelasnya: Operator Bersyarat
sumber
Baris kesalahan "Referensi objek tidak disetel ke instance objek." Menyatakan bahwa Anda belum menetapkan objek instance ke referensi objek dan Anda masih mengakses properies / metode objek itu.
misalnya: katakanlah Anda memiliki kelas yang disebut myClass dan mengandung satu properti prop1.
Sekarang Anda mengakses prop1 ini di beberapa kelas lain seperti di bawah ini:
baris di atas melempar kesalahan karena referensi kelas myClass dideklarasikan tetapi tidak instantiated atau turunan objek tidak ditugaskan ke referecne dari kelas itu.
Untuk memperbaiki ini, Anda harus instantiate (menetapkan objek untuk referensi kelas itu).
sumber
Referensi NullReferenceException atau Obyek yang tidak disetel ke instance objek terjadi ketika objek kelas yang Anda coba gunakan tidak instantiated. Sebagai contoh:
Asumsikan bahwa Anda memiliki kelas bernama Siswa.
Sekarang, pertimbangkan kelas lain tempat Anda mencoba mengambil nama lengkap siswa.
Seperti terlihat pada kode di atas, pernyataan Siswa s - hanya menyatakan variabel tipe Siswa, perhatikan bahwa kelas Siswa tidak dipakai pada saat ini. Oleh karena itu, ketika pernyataan s.GetFullName () dijalankan, itu akan membuang NullReferenceException.
sumber
Nah, secara sederhana:
Anda mencoba mengakses objek yang tidak dibuat atau saat ini tidak ada dalam memori.
Jadi bagaimana cara mengatasinya:
Debug dan biarkan debugger istirahat ... Ini akan langsung membawa Anda ke variabel yang rusak ... Sekarang tugas Anda adalah hanya memperbaiki ini .. Menggunakan kata kunci baru di tempat yang tepat.
Jika itu disebabkan pada beberapa perintah database karena objek tidak ada maka yang perlu Anda lakukan adalah melakukan centang nol dan menanganinya:
Yang paling sulit .. jika GC mengumpulkan objek sudah ... Ini umumnya terjadi jika Anda mencoba untuk menemukan objek menggunakan string ... Artinya, menemukannya dengan nama objek maka dapat terjadi bahwa GC mungkin sudah membersihkannya ... Ini sulit ditemukan dan akan menjadi cukup masalah ... Cara yang lebih baik untuk mengatasi ini adalah melakukan pemeriksaan nol di mana pun diperlukan selama proses pengembangan. Ini akan menghemat banyak waktu.
Dengan mencari dengan nama saya maksudkan beberapa kerangka kerja memungkinkan Anda untuk FIndObjects menggunakan string dan kode mungkin terlihat seperti ini: FindObject ("ObjectName");
sumber
Secara harfiah cara termudah untuk memperbaiki NullReferenceExeption memiliki dua cara. Jika Anda memiliki GameObject misalnya dengan skrip yang dilampirkan dan variabel bernama rb (rigidbody) variabel ini akan mulai nol ketika Anda memulai permainan.
Inilah sebabnya mengapa Anda mendapatkan NullReferenceExeption karena komputer tidak memiliki data yang disimpan dalam variabel itu.
Saya akan menggunakan variabel RigidBody sebagai contoh.
Kami dapat menambahkan data dengan sangat mudah sebenarnya dalam beberapa cara:
Kemudian masuk ke skrip Anda dan ketik
rb = GetComponent<Rigidbody>();
Baris kode ini bekerja paling baik di bawah Anda
Start()
atauAwake()
fungsi.rb = AddComponent<RigidBody>();
Catatan lebih lanjut: Jika Anda ingin kesatuan untuk menambahkan komponen ke objek Anda dan Anda mungkin lupa menambahkannya, Anda bisa mengetikkan di
[RequireComponent(typeof(RigidBody))]
atas deklarasi kelas Anda (ruang di bawah semua usings Anda).Nikmati dan bersenang-senang membuat game!
sumber
Jika kami mempertimbangkan skenario umum di mana pengecualian ini dapat dilempar, mengakses properti dengan objek di atas.
Ex:
di sini, jika alamatnya nol, maka Anda akan mendapatkan NullReferenceException.
Jadi, sebagai praktik, kita harus selalu menggunakan cek kosong, sebelum mengakses properti di objek tersebut (khususnya dalam generik)
sumber
Ini pada dasarnya adalah pengecualian referensi Null . Sebagai Microsoft menyatakan-
Apa artinya?
Itu berarti jika ada anggota yang tidak memiliki nilai apa pun dan kami membuat anggota itu untuk melakukan tugas tertentu, maka sistem tidak diragukan lagi akan melemparkan pesan dan berkata-
"Hei, tunggu, anggota itu tidak memiliki nilai sehingga tidak bisa melakukan tugas yang kamu serahkan."
Pengecualian itu sendiri mengatakan bahwa sesuatu sedang dirujuk tetapi nilainya tidak ditetapkan. Jadi ini menunjukkan bahwa itu hanya terjadi saat menggunakan tipe referensi karena tipe Value tidak dapat dibatalkan.
NullReferenceException tidak akan terjadi jika kita menggunakan anggota tipe Nilai.
Kode di atas menunjukkan string sederhana yang ditugaskan dengan null nilai .
Sekarang, ketika saya mencoba untuk mencetak panjang string str , saya mendapatkan pengecualian yang tidak tertangani dari tipe 'System.NullReferenceException' terjadi pesan karena anggota str menunjuk ke nol dan tidak mungkin ada panjang nol.
' NullReferenceException ' juga terjadi ketika kita lupa untuk instantiate jenis referensi.
Misalkan saya memiliki metode kelas dan anggota di dalamnya. Saya belum membuat kelas saya tetapi hanya memberi nama kelas saya. Sekarang jika saya mencoba menggunakan metode ini, kompiler akan melemparkan kesalahan atau mengeluarkan peringatan (tergantung pada kompiler).
Kompiler untuk kode di atas menimbulkan kesalahan bahwa variabel obj tidak ditetapkan yang menandakan bahwa variabel kami memiliki nilai nol atau tidak sama sekali. Kompiler untuk kode di atas menimbulkan kesalahan bahwa variabel obj tidak ditetapkan yang menandakan bahwa variabel kami memiliki nilai nol atau tidak sama sekali.
Kenapa itu terjadi?
NullReferenceException muncul karena kesalahan kami karena tidak memeriksa nilai objek. Kami sering membiarkan nilai objek tidak dicentang dalam pengembangan kode.
Itu juga muncul ketika kita lupa untuk instantiate objek kita. Menggunakan metode, properti, koleksi dll. Yang dapat mengembalikan atau menetapkan nilai nol juga bisa menjadi penyebab pengecualian ini.
Bagaimana itu bisa dihindari?
Ada berbagai cara dan metode untuk menghindari pengecualian terkenal ini:
Pemeriksaan Eksplisit: Kita harus mematuhi tradisi untuk memeriksa objek, properti, metode, array, dan koleksi apakah itu nol. Ini dapat dengan mudah diimplementasikan menggunakan pernyataan kondisional seperti if-else if-else dll.
Penanganan pengecualian: Salah satu cara penting untuk mengelola pengecualian ini. Dengan menggunakan blok coba-tangkap-akhirnya yang sederhana, kita dapat mengontrol pengecualian ini dan juga menyimpan lognya. Ini bisa sangat berguna ketika aplikasi Anda sedang dalam tahap produksi.
Operator kosong: Operator penggabungan nol dan operator kondisional nol juga dapat digunakan dengan praktis saat menetapkan nilai ke objek, variabel, properti, dan bidang.
Debugger: Untuk pengembang, kami memiliki senjata besar untuk debugging bersama kami. Jika kita menghadapi NullReferenceException selama pengembangan wajah kita dapat menggunakan debugger untuk sampai ke sumber pengecualian.
Metode bawaan: Metode sistem seperti GetValueOrDefault (), IsNullOrWhiteSpace () dan IsNullorEmpty () memeriksa nulls dan menetapkan nilai default jika ada nilai nol.
Ada banyak jawaban bagus di sini. Anda juga dapat memeriksa deskripsi yang lebih rinci dengan contoh di blog saya .
Semoga ini bisa membantu juga!
sumber
Jika seseorang mendapatkan pesan ini selama menyimpan atau mengkompilasi build, tutup saja semua file dan kemudian buka file apa saja untuk dikompilasi dan disimpan.
Bagi saya alasannya adalah bahwa saya telah mengganti nama file dan file lama masih terbuka.
sumber