Apa itu NullReferenceException, dan bagaimana cara memperbaikinya?


1875

Saya memiliki beberapa kode dan ketika dijalankan, ia melempar NullReferenceException, mengatakan:

Referensi objek tidak disetel ke instance objek.

Apa artinya ini, dan apa yang bisa saya lakukan untuk memperbaiki kesalahan ini?


Pembantu pengecualian di VS 2017 akan lebih membantu dalam mendiagnosis penyebab pengecualian ini - blogs.msdn.microsoft.com/visualstudio/2016/11/28/… di bawah New Exception Helper .
Zev Spitz

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 null dalam metode "A", bisa jadi metode "B" meneruskan null ke metode "A".

null dapat memiliki arti yang berbeda:

    1. 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.
    1. 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 NullReferenceException 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) 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:

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

Secara khusus, dalam HttpContext.Current.User.Identity.Name, HttpContext.Currentbisa jadi nol, atau Userproperti bisa nol, atau Identityproperti bisa nol.

Tidak langsung

public class Person 
{
    public int Age { get; set; }
}
public class Book 
{
    public Person Author { get; set; }
}
public class Example 
{
    public void Foo() 
    {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; // You never initialized the Author property.
                                       // there is no Person to get an Age from.
    }
}

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 = new Book 
{ 
   Author = { Age = 45 } 
};

Ini diterjemahkan menjadi

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

Sementara newkata kunci digunakan, itu hanya membuat contoh baru Book, tetapi bukan contoh baru Person, sehingga Authorproperti tetap null.

Inisialisasi Koleksi Bersarang

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

Koleksi bersarang Initializersberperilaku sama:

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

Ini diterjemahkan menjadi

Person p1 = new Person();
p1.Books.Add(new Book { Title = "Title1" });
p1.Books.Add(new Book { 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 = new Person[5];
people[0].Age = 20 // people[0] is null. The array was allocated but not
                   // initialized. There is no Person to set the Age for.

Array bergerigi

long[][] array = new long[1][];
array[0][0] = 3; // is null because only the first dimension is yet initialized.
                 // Use array[0] = new long[2]; first.

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)

public class Person 
{
    public string Name { get; set; }
}
var people = new List<Person>();
people.Add(null);
var names = from p in people select p.Name;
string firstName = names.First(); // Exception is thrown here, but actually occurs
                                  // on the line above.  "p" is null because the
                                  // first element we added to the list is null.

Acara

public class Demo
{
    public event EventHandler StateChanged;

    protected virtual void OnStateChanged(EventArgs e)
    {        
        StateChanged(this, e); // Exception is thrown here 
                               // if no event handlers have been attached
                               // to StateChanged event
    }
}

###Bad Naming Conventions:

If you named fields differently from locals, you might have realized that you never initialized the field. 

kelas publik Form1 {pelanggan Pelanggan pribadi;

private void Form1_Load(object sender, EventArgs e) 
{
    Customer customer = new Customer();
    customer.Name = "John";
}

private void Button_Click(object sender, EventArgs e)
{
    MessageBox.Show(customer.Name);
}

}

Ini dapat dipecahkan dengan mengikuti konvensi ke bidang awalan dengan garis bawah:

    private Customer _customer;

ASP.NET Page Life cycle:

public partial class Issues_Edit : System.Web.UI.Page
{
    protected TestIssue myIssue;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
             // Only called on first load, not when button clicked
             myIssue = new TestIssue(); 
        }
    }

    protected void SaveButton_Click(object sender, EventArgs e)
    {
        myIssue.Entry = "NullReferenceException here!";
    }
}

Nilai Sesi ASP.NET

// if the "FirstName" session value has not yet been set,
// then this line will throw a NullReferenceException
string 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:

// Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
        return View();  // Forgot the provide a Model here.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Throws.
{
}

<p>@Model.somePropertyName</p> <!-- Also throws -->

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 -->
    <ComboBox Name="comboBox1" 
              Margin="10"
              SelectedIndex="0" 
              SelectionChanged="comboBox1_SelectionChanged">
       <ComboBoxItem Content="Item 1" />
       <ComboBoxItem Content="Item 2" />
       <ComboBoxItem Content="Item 3" />
    </ComboBox>

    <!-- Label declared later -->
    <Label Name="label1" 
           Content="Label"
           Margin="10" />
</Grid>

Di sini comboBox1dibuat sebelumnya label1. Jika comboBox1_SelectionChangedupaya untuk mereferensikan `label1, itu belum akan dibuat.

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

Mengubah urutan deklarasi dalam XAML(yaitu, daftar label1sebelumnya comboBox1, mengabaikan masalah filosofi desain, setidaknya akan menyelesaikan di NullReferenceExceptionsini.

Dipadukan dengan as

var myThing = someObject as Thing;

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:

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

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:

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

Periksa secara eksplisit nulldari panggilan metode dan berikan pengecualian khusus.

Anda juga dapat melempar pengecualian khusus, hanya untuk menangkapnya dalam kode panggilan:

string GetCategory(string bookTitle) 
{
    var book = library.FindBook(bookTitle);  // This may return null
    if (book == null)
        throw new BookNotFoundException(bookTitle);  // Your custom exception
    return book.Category;
}

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:

string GetTitle(int knownBookID) 
{
    // You know this should never return null.
    var book = library.GetBook(knownBookID);  

    // Exception will occur on the next line instead of at the end of this method.
    Debug.Assert(book != null, "Library didn't return a book for known book ID.");

    // Some other code

    return book.Title; // Will never throw NullReferenceException in Debug mode.
}

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 = new DateTime(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:

IService CreateService(ILogger log, Int32? frobPowerLevel)
{
   var serviceImpl = new MyService(log ?? NullLog.Instance);

   // Note that the above "GetValueOrDefault()" can also be rewritten to use
   // the coalesce operator:
   serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5;
}

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 check
int titleLength = 0;
if (title != null)
    titleLength = title.Length; // If title is null, this would throw NullReferenceException

// combining the `?` and the `??` operator
int titleLength = title?.Length ?? 0;

Demikian juga, untuk array Anda dapat menggunakan ?[i]sebagai berikut:

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

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:

public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    for (int i = 0; i < count; ++i)
    yield return f.MakeFrob();
}
...
FrobFactory factory = whatever;
IEnumerable<Frobs> frobs = GetFrobs();
...
foreach(Frob frob in frobs) { ... }

Jika whateverhasilnya nullmaka MakeFrobakan melempar. Sekarang, Anda mungkin berpikir bahwa hal yang benar untuk dilakukan adalah ini:

// DON'T DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
   if (f == null) 
      throw new ArgumentNullException("f", "factory must not be null");
   for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}

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 THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
   // No yields in a public method that throws!
   if (f == null) 
       throw new ArgumentNullException("f", "factory must not be null");
   return GetFrobsForReal(f, count);
}
private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count)
{
   // Yields in a private method
   Debug.Assert(f != null);
   for (int i = 0; i < count; ++i)
        yield return f.MakeFrob();
}

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.


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

  1. 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.
  2. Contoh-contoh (dari posting Stack Overflow) tidak selalu menunjukkan cara terbaik untuk melakukan sesuatu.
  3. 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.

Tampilan debug IDE

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.

Lihat juga:

Contoh dan Solusi

Objek Kelas / Membuat Instance

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 As New CashRegister        ' [New] creates instance, invokes the constructor

' Longer, more explicit form:
Dim reg As CashRegister = New CashRegister

Saat yang tepat untuk membuat instance nanti:

Private reg As CashRegister         ' Declare
  ...
reg = New CashRegister()            ' Create instance

Catatan: Jangan gunakan Dimlagi dalam prosedur, termasuk konstruktor ( Sub New):

Private reg As CashRegister
'...

Public Sub New()
   '...
   Dim reg As New CashRegister
End Sub

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 .

Untuk informasi lebih lanjut, lihat:


Array

Array juga harus dipakai:

Private arr as String()

Array ini hanya dideklarasikan, tidak dibuat. Ada beberapa cara untuk menginisialisasi array:

Private arr as String() = New String(10){}
' or
Private arr() As String = New String(10){}

' For a local array (in a procedure) and using 'Option Infer':
Dim arr = New String(10) {}

Catatan: Dimulai dengan VS 2010, ketika menginisialisasi array lokal menggunakan literal dan Option Infer, elemen As <Type>dan Newopsional:

Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14}
Dim myDbl = New Double() {1.5, 2, 9.9, 18, 3.14}
Dim myDbl() = {1.5, 2, 9.9, 18, 3.14}

Tipe data dan ukuran array disimpulkan dari data yang ditugaskan. Tingkat deklarasi kelas / Modul masih memerlukan As <Type>dengan Option Strict:

Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}

Contoh: Array objek kelas

Dim arrFoo(5) As Foo

For i As Integer = 0 To arrFoo.Count - 1
   arrFoo(i).Bar = i * 10       ' Exception
Next

Array telah dibuat, tetapi Fooobjek di dalamnya belum.

Obat

For i As Integer = 0 To arrFoo.Count - 1
    arrFoo(i) = New Foo()         ' Create Foo instance
    arrFoo(i).Bar = i * 10
Next

Menggunakan List(Of T)akan membuatnya sangat sulit untuk memiliki elemen tanpa objek yang valid:

Dim FooList As New List(Of Foo)     ' List created, but it is empty
Dim f As Foo                        ' Temporary variable for the loop

For i As Integer = 0 To 5
    f = New Foo()                    ' Foo instance created
    f.Bar =  i * 10
    FooList.Add(f)                   ' Foo object added to list
Next

Untuk informasi lebih lanjut, lihat:


Daftar dan Koleksi

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 As New List(Of String)

Pengawasan umum adalah kelas yang menggunakan koleksi Type:

Public Class Foo
    Private barList As List(Of Bar)

    Friend Function BarCount As Integer
        Return barList.Count
    End Function

    Friend Sub AddItem(newBar As Bar)
        If barList.Contains(newBar) = False Then
            barList.Add(newBar)
        End If
    End Function

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:

Public Sub New         ' Constructor
    ' Stuff to do when a new Foo is created...
    barList = New List(Of Bar)
End Sub

Seperti sebelumnya, ini tidak benar:

Public Sub New()
    ' Creates another barList local to this procedure
     Dim barList As New List(Of Bar)
End Sub

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

Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows As Integer

con.Open()
Dim sql = "SELECT * FROM tblfoobar_List"
da = New OleDbDataAdapter(sql, con)
da.Fill(ds, "foobar")
con.Close()

MaxRows = ds.Tables("foobar").Rows.Count      ' Error

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:

img

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

Dim ds As New DataSet

Contoh 2

ds = New DataSet
da = New OleDBDataAdapter(sql, con)
da.Fill(ds, "Employees")

txtID.Text = ds.Tables("Employee").Rows(0).Item(1)
txtID.Name = ds.Tables("Employee").Rows(0).Item(2)

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 > 0 Then
    txtID.Text = ds.Tables(0).Rows(0).Item(1)
    txtID.Name = ds.Tables(0).Rows(0).Item(2)
End If

Filladalah fungsi mengembalikan jumlah yang Rowsterpengaruh yang juga dapat diuji:

If da.Fill(ds, "Employees") > 0 Then...

Contoh 3

Dim da As New OleDb.OleDbDataAdapter("SELECT TICKET.TICKET_NO,
        TICKET.CUSTOMER_ID, ... FROM TICKET_RESERVATION AS TICKET INNER JOIN
        FLIGHT_DETAILS AS FLIGHT ... WHERE [TICKET.TICKET_NO]= ...", con)
Dim ds As New DataSet
da.Fill(ds)

If ds.Tables("TICKET_RESERVATION").Rows.Count > 0 Then

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:

If ds.Tables(0).Rows.Count > 0 Then

Lihat juga Kelas DataTable .


Jalur Objek / Bersarang

If myFoo.Bar.Items IsNot Nothing Then
   ...

Kode hanya menguji Itemssementara keduanya myFoodan Barmungkin juga Tidak Ada. The obat adalah untuk menguji seluruh rantai atau jalur objek satu per satu:

If (myFoo IsNot Nothing) AndAlso
    (myFoo.Bar IsNot Nothing) AndAlso
    (myFoo.Bar.Items IsNot Nothing) Then
    ....

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:

myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")

Tidak mungkin untuk merujuk apa pun 'hilir' dari suatu nullobjek. Ini juga berlaku untuk kontrol:

myWebBrowser.Document.GetElementById("formfld1").InnerText = "some value"

Di sini, myWebBrowseratau Documentbisa jadi Tidak ada atau formfld1elemen mungkin tidak ada.


Kontrol UI

Dim cmd5 As New SqlCommand("select Cartons, Pieces, Foobar " _
     & "FROM Invoice where invoice_no = '" & _
     Me.ComboBox5.SelectedItem.ToString.Trim & "' And category = '" & _
     Me.ListBox1.SelectedItem.ToString.Trim & "' And item_name = '" & _
     Me.ComboBox2.SelectedValue.ToString.Trim & "' And expiry_date = '" & _
     Me.expiry.Text & "'", con)

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 validation
If (ComboBox5.SelectedItems.Count > 0) AndAlso
    (ListBox1.SelectedItems.Count > 0) AndAlso
    (ComboBox2.SelectedItems.Count > 0) AndAlso
    (DateTime.TryParse(expiry.Text, expiry) Then

    '... do stuff
Else
    MessageBox.Show(...error message...)
End If

Atau, Anda dapat menggunakan (ComboBox5.SelectedItem IsNot Nothing) AndAlso...


Bentuk Visual Basic

Public Class Form1

    Private NameBoxes = New TextBox(5) {Controls("TextBox1"), _
                   Controls("TextBox2"), Controls("TextBox3"), _
                   Controls("TextBox4"), Controls("TextBox5"), _
                   Controls("TextBox6")}

    ' same thing in a different format:
    Private boxList As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}

    ' Immediate NRE:
    Private somevar As String = Me.Controls("TextBox1").Text

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 As String = NameBoxes(2).Text        ' NRE
   ' ...
   ' More code (which will likely not be executed)
   ' ...
End Sub

Catatan ini berlaku untuk setiap dan semua kontrol dan referensi komponen membuat ini ilegal di mana mereka berada:

Public Class Form1

    Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
    Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
    Private studentName As String = TextBox13.Text

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 Newselama kode Anda setelah InitializeComponentpanggilan:

' Module level declaration
Private NameBoxes as TextBox()
Private studentName As String

' Form Load, Form Shown or Sub New:
'
' Using the OP's approach (illegal using OPTION STRICT)
NameBoxes = New TextBox() {Me.Controls("TextBox1"), Me.Controls("TestBox2"), ...)
studentName = TextBox32.Text           ' For simple control references

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: VS menunjukkan kesalahan cara Anda

"Button2" berada di a Panel

Obat

Daripada referensi tidak langsung dengan nama menggunakan Controlskoleksi formulir , gunakan referensi kontrol:

' Declaration
Private NameBoxes As TextBox()

' Initialization -  simple and easy to read, hard to botch:
NameBoxes = New TextBox() {TextBox1, TextBox2, ...)

' Initialize a List
NamesList = New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})
' or
NamesList = New List(Of TextBox)
NamesList.AddRange({TextBox1, TextBox2, TextBox3...})

Tidak Mengembalikan Fungsi

Private bars As New List(Of Bars)        ' Declared and created

Public Function BarList() As List(Of Bars)
    bars.Clear
    If someCondition Then
        For n As Integer = 0 to someValue
            bars.Add(GetBar(n))
        Next n
    Else
        Exit Function
    End If

    Return bars
End Function

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()
For Each b As Bar in bList      ' EXCEPTION
      ...

Obat

Ganti Exit Functionfungsi dengan Return bList. Mengembalikan kosong List tidak sama dengan mengembalikan Nothing. Jika ada kemungkinan objek yang dikembalikan dapat Nothing, uji sebelum menggunakannya:

 bList = myFoo.BarList()
 If bList IsNot Nothing Then...

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
Try
    Dim lnk As LinkButton = TryCast(sender, LinkButton)
    Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow)
    Dim eid As String = GridView1.DataKeys(gr.RowIndex).Value.ToString()
    ViewState("username") = eid
    sqlQry = "select FirstName, Surname, DepartmentName, ExtensionName, jobTitle,
             Pager, mailaddress, from employees1 where username='" & eid & "'"
    If connection.State <> ConnectionState.Open Then
        connection.Open()
    End If
    command = New SqlCommand(sqlQry, connection)

    'More code fooing and barring

    dr = command.ExecuteReader()
    If dr.Read() Then
        lblFirstName.Text = Convert.ToString(dr("FirstName"))
        ...
    End If
    mpe.Show()
Catch

Finally
    command.Dispose()
    dr.Close()             ' <-- NRE
    connection.Close()
End Try

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

For Each row As DataGridViewRow In dgvPlanning.Rows
    If Not 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 Nothing Then ...

Seperti sebelumnya, Anda dapat menguji Tidak Ada, kemudian untuk nilai tertentu:

If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then

Contoh 2

Dim getFoo = (From f In dbContext.FooBars
               Where f.something = something
               Select f).FirstOrDefault

If Not IsDBNull(getFoo) Then
    If IsDBNull(getFoo.user_id) Then
        txtFirst.Text = getFoo.first_name
    Else
       ...

FirstOrDefaultmengembalikan item pertama atau nilai default, yang Nothinguntuk tipe referensi dan tidak pernah DBNull:

If getFoo IsNot Nothing Then...

Kontrol

Dim chk As CheckBox

chk = CType(Me.Controls(chkName), CheckBox)
If chk.Checked Then
    Return chk
End If

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:

dgvBooks.DataSource = loan.Books
dgvBooks.Columns("ISBN").Visible = True       ' NullReferenceException
dgvBooks.Columns("Title").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Author").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Price").DefaultCellStyle.Format = "C"

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:

dgvBooks.Columns(0).Visible = True

Contoh 2 - Waspadalah terhadap NewRow

xlWorkSheet = xlWorkBook.Sheets("sheet1")

For i = 0 To myDGV.RowCount - 1
    For j = 0 To myDGV.ColumnCount - 1
        For k As Integer = 1 To myDGV.Columns.Count
            xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText
            xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString()
        Next
    Next
Next

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:

For Each r As DataGridViewRow in myDGV.Rows
    If r.IsNewRow = False Then
         ' 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 Is Nothing Then
    My.Settings.FooBars = New System.Collections.Specialized.StringCollection
End If

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


Pengecualian NullReference MSDN


226

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:

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

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


7
Tangkapan yang bagus. Cara satu-liner untuk menghindari:DateTime x = (DateTime) o as DateTime? ?? defaultValue;
Serge Shultz

160

Ini berarti bahwa variabel yang dipermasalahkan tidak menunjuk apa-apa. Saya dapat menghasilkan ini seperti ini:

SqlConnection connection = null;
connection.Open();

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:

  1. Selalu inisialisasi objek Anda sebelum Anda mencoba melakukan apa pun dengannya.
  2. 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.


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

96

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.


87

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.

Informasi lebih lanjut ada di C # NullReferenceException dan Null Parameter .


87

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:

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.

Jenis referensi (yang ini harus diperiksa):

  • dinamis
  • obyek
  • tali

Jenis nilai (Anda dapat mengabaikannya):

  • Jenis numerik
  • Tipe integral
  • Jenis titik mengambang
  • desimal
  • bool
  • Struktur yang ditentukan pengguna

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

class Book {
    public string Name { get; set; }
}
class Car { }

Car mycar = new Car();
Book mybook = mycar as Book;   // Incompatible conversion --> mybook = null

Console.WriteLine(mybook.Name);   // NullReferenceException

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:

ComicBook cb = specificBook as ComicBook;
if (cb != null) {
   // ...
}

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

string value = 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 ()


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

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


59

Simon Mourier memberi contoh ini :

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

di mana konversi unboxing (dilemparkan) dari object (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 false untuk 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:

public static void MyExtension(this object x)
{
  x.ToString();
}

kode berikut akan bermasalah:

DateTime? d = null;
d.MyExtension();  // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.

Kasus-kasus ini muncul karena aturan khusus yang digunakan runtime ketika Nullable<>instance tinju .


42

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 = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line

Demi kelengkapan kelas DataContext

public class DataContext : DbContext 
{
    public DbSet<Contact> Contacts {get; set;}
}

dan kelas entitas kontak. Kadang-kadang kelas entitas adalah kelas parsial sehingga Anda dapat memperluas mereka di file lain juga.

public partial class Contact 
{
    public string Name {get; set;}
}

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


41

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.

Lihat " NullReferenceException yang dilemparkan ketika menguji custom AuthorizationAttribute " untuk contoh yang agak bertele-tele.


40

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.

public class MyController
{
    private ServiceA serviceA;
    private ServiceB serviceB;

    public MyController(ServiceA serviceA, ServiceB serviceB)
    {
        this.serviceA = serviceA;
        this.serviceB = serviceB;
    }

    public void MyMethod()
    {
        // We don't need to check null because the dependency injection container 
        // injects it, provided you took care of bootstrapping it.
        var someObject = serviceA.DoThis();
    }
}

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

public void InvokeX()
{
    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]
protected void ObjectInvariant () 
{
    Contract.Invariant ( X != null );
    //...
}

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 .


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

Sebagai contoh:

  1. Ketika metode string dari string kosong diakses:

    string str = string.Empty;
    str.ToLower(); // throw null reference exception
  2. Ketika properti objek null diakses:

    Public Class Person {
        public string Name { get; set; }
    }
    Person objPerson;
    objPerson.Name  /// throw Null refernce Exception 

2
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.
Kjartan

31

TL; DR: Coba gunakan Html.Partialsebagai 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:

@{
    MyEntity M = new MyEntity();
}
@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 = new MyEntity();
}
@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:

@inherits System.Web.Mvc.WebViewPage
@{
    ViewBag.Title = "Entity Index";
    List<MyEntity> MyEntities = new List<MyEntity>();
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
}
<div>
    @{
        foreach(var M in MyEntities)
        {
            // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
            @Html.Partial("MyOtherView.cshtml");
        }
    }
</div>

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

Meskipun saya merasa itu karena Visual Studio salah membaca tanda kurung dan kurung.


Anda ingin Html.Partial, bukan@Html.Partial
John Saunders

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.

public void DoSomething(MyObject obj) {
    if(obj == null) 
    {
        throw new ArgumentNullException("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:

public void DoSometing([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]
public struct NotNull<T> where T: class
{
    private T _value;

    public T Value
    {
        get
        {
            if (_value == null)
            {
                throw new Exception("null value not allowed");
            }

            return _value;
        }
        set
        {
            if (value == null)
            {
                throw new Exception("null value not allowed.");
            }

            _value = value;
        }
    }

    public static implicit operator T(NotNull<T> notNullValue)
    {
        return notNullValue.Value;
    }

    public static implicit operator NotNull<T>(T value)
    {
        return new NotNull<T> { Value = value };
    }
}

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 exception
NotNull<Person> person = new Person(); // OK
NotNull<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 = new Person { Name = "John" };
WriteName(person);

public static void WriteName(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();

public static NotNull<Person> GetPerson()
{
    return new Person { 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();

public static Person GetPerson()
{
    return new Person { 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]
public static class NotNullExtension
{
    public static T NotNull<T>(this T @this) where T: class
    {
        if (@this == null)
        {
            throw new Exception("null value not allowed");
        }

        return @this;
    }
}

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:

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


2
Jangan pernah melempar NullReferenceException
John Saunders

@ JohnSaunders berani saya bertanya mengapa? (Serius, mengapa?)
Luis Perez

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


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

Untuk lebih jelasnya: Operator Bersyarat


9

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.

public Class myClass
{
   public int prop1 {get;set;}
}

Sekarang Anda mengakses prop1 ini di beberapa kelas lain seperti di bawah ini:

public class Demo
{
     public void 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).

public class Demo
{
     public void testMethod()
     {
        myClass ref = null;
        ref = new myClass();
        ref.prop1 = 1;  
     }
}

4

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.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}

Sekarang, pertimbangkan kelas lain tempat Anda mencoba mengambil nama lengkap siswa.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

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.


3

Nah, secara sederhana:

Anda mencoba mengakses objek yang tidak dibuat atau saat ini tidak ada dalam memori.

Jadi bagaimana cara mengatasinya:

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

  2. 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
    }
  3. 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");


3
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.
Akash Gutha

2
docs.unity3d.com/ScriptReference/… periksa tautan dan perbaiki urself mr.expert: p
Akash Gutha

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:

  1. 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.
  2. 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!


-1

Jika kami mempertimbangkan skenario umum di mana pengecualian ini dapat dilempar, mengakses properti dengan objek di atas.

Ex:

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

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)

string postalcode=Customer?.Address?.PostalCode;
//if customer or address is null , this will return null, without through a exception

-3

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.

class Program
{
    static void Main(string[] args)
    {
        string str = null;
        Console.WriteLine(str.Length);
        Console.ReadLine();
    }
}

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

class Program
{
    static void Main(string[] args)
    {
        MyClass1 obj;
        obj.foo();  //Use of unassigned local variable 'obj'
    }
}

public class MyClass1
{
    internal void foo()
    {
        Console.WriteLine("hello from foo");

    }
}

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:

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

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

  3. Operator kosong: Operator penggabungan nol dan operator kondisional nol juga dapat digunakan dengan praktis saat menetapkan nilai ke objek, variabel, properti, dan bidang.

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

  5. 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!


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.