NullReferenceException nedir ve nasıl düzeltebilirim?


1875

Bazı kod var ve çalıştırdığında, atar NullReferenceException, atar :

Nesne referansı bir nesnenin örneğine atanmadı.

Bu ne anlama geliyor ve bu hatayı düzeltmek için ne yapabilirim?


- VS 2017 yılında istisna yardımcı bu özel durumun nedenini teşhis daha yararlı olacaktır blogs.msdn.microsoft.com/visualstudio/2016/11/28/... altında Yeni İstisna Yardımcısı .
Zev Spitz

Değerli gelecekteki ziyaretçiler, bu sorunun yanıtları bir ArgumentNullException için de geçerlidir . Sorunuz bunun bir kopyası olarak kapatıldıysa ve bir ANE yaşıyorsanız, lütfen hata ayıklamak ve sorununuzu çözmek için cevaplardaki talimatları izleyin.

@ ANE yalnızca parametre olarak bir null iletilirse gerçekleşir. Bir ANE sorusu bunun bir kopyası olarak kapandıysa bir örnek verebilir misiniz?
John Saunders

Meta'da ortaya çıktı, ama bağlantı için kazmaya gitmeliyim. Ancak bu yoruma gelince, bir ANE sadece bir NRE'dir, ancak birisi önleyici bir kontrol ekledi ve en azından null olduğunu tam olarak biliyorsunuz (argüman adı sağlandı), bu yüzden teşhis etmek düz bir NRE'den biraz daha kolay.

Yanıtlar:


2415

Sebebi nedir?

Sonuç olarak

null(Veya NothingVB.NET içinde) bir şey kullanmaya çalışıyorsunuz . Bu, ya ayarladığınız ya nullda hiçbir şeye ayarlayamayacağınız anlamına gelir .

Diğer her şey gibi, nulletrafından geçilir. Eğer durum bu ise null de yöntemin "A", o yöntem "B" geçmiş olabilir null için yöntemin "A".

null farklı anlamları olabilir:

    1. Başlatılmamış ve dolayısıyla hiçbir şeye işaret etmeyen nesne değişkenleri . Bu durumda, bu tür nesnelerin özelliklerine veya yöntemlerine erişirseniz, bu durum a NullReferenceException.
    1. Geliştirici, anlamlı bir değer olmadığını belirtmek için nullkasıtlı olarak kullanıyor . C # değişkenleri için null olabilecek veri türleri kavramına sahip olduğunu unutmayın (veritabanı tabloları nullable alanları olabilir gibi) - nullbunlara depolanmış bir değer olmadığını belirtmek için atayabilirsiniz , örneğin int? a = null;soru işareti null değerinin depolanmasına izin verildiğini gösterir değişken a. Bunu ile if (a.HasValue) {...}veya ile kontrol edebilirsiniz if (a==null) {...}. aBu örnek gibi nullable değişkenleri, değere a.Valueaçıkça veya normal şekilde erişilmesine izin verir a.
      Not üzerinden eriştiğini o a.Valuebir atar InvalidOperationExceptionyerine ait NullReferenceExceptionise a, ISnull- kontrolü önceden yapmalısınız, yani başka bir nullenebilen değişkeniniz int b;varsa, o zaman if (a.HasValue) { b = a.Value; }daha kısa ya da böyle atamalar yapmalısınız if (a != null) { b = a; }.

Bu makalenin geri kalan birçok programcılar genellikle yol açabilir yapmak daha detay ve gösteriler hatalardan gider NullReferenceException.

Daha Özel

runtimeBir atma NullReferenceException hep bir başvuru kullanmaya çalıştığınız ve referans başlatılmadı (veya edildi: Aynı şeyi ifade kere başlatıldı, ancak artık başlatıldı).

Bu, başvurunun olduğu nullve bir nullbaşvuru yoluyla üyelere (yöntemler gibi) erişemeyeceğiniz anlamına gelir . En basit durum:

string foo = null;
foo.ToUpper();

Bu NullReferenceException, ikinci satıra a atar çünkü işaret eden ToUpper()bir stringbaşvuruda örnek yöntemini çağıramazsınız null.

Hata ayıklama

A'nın kaynağını nasıl buldunuz NullReferenceException? Bunun dışında meydana yerde tam olarak atılacaktır istisna kendisi bakarak, Visual Studio'da hata ayıklama genel kurallar geçerlidir: yer stratejik kesme noktaları ve sizin değişkenleri inceleyin , ya bir (açılış, isimleri üzerine fare gelerek Hızlı) Pencereyi izleyin veya Locals ve Autos gibi çeşitli hata ayıklama panellerini kullanın.

Referansın nerede ayarlandığını veya ayarlanmadığını öğrenmek istiyorsanız, adını sağ tıklayın ve "Tüm Referansları Bul" u seçin. Daha sonra bulunan her konuma bir kesme noktası yerleştirebilir ve hata ayıklayıcı eklenmiş olarak programınızı çalıştırabilirsiniz. Hata ayıklayıcı böyle bir kesme noktasını her kırdığında, başvurunun boş olmamasını bekleyip beklemediğinizi belirlemeniz, değişkeni denetlemeniz ve beklediğinizde bir örneği gösterdiğini doğrulamanız gerekir.

Program akışını bu şekilde izleyerek, örneğin null olmaması gereken konumu ve neden düzgün ayarlanmadığını bulabilirsiniz.

Örnekler

İstisnanın atılabileceği bazı yaygın senaryolar:

genel

ref1.ref2.ref3.member

Ref1 veya ref2 veya ref3 boşsa, bir NullReferenceException. Sorunu çözmek istiyorsanız, ifadeyi daha basit eşdeğerine yeniden yazarak hangisinin boş olduğunu bulun:

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

Özellikle, içinde HttpContext.Current.User.Identity.Name, HttpContext.Currentboş olabilir veya Userözelliği null olabilir veya Identityözelliği null olabilir.

Dolaylı

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

Alt (Kişi) null başvurusundan kaçınmak isterseniz, üst öğe (Kitap) nesnesinin yapıcısında başlatabilirsiniz.

Yuvalanmış Nesne Başlatıcılar

Aynı şey iç içe nesne başlatıcıları için de geçerlidir:

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

Bu şu anlama gelir

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

İken newanahtar kullanılır, sadece yeni bir örneğini oluşturur Bookyeni bir örneğini değil, Personbu yüzden, Authormülkiyet hala null.

Yuvalanmış Koleksiyon Başlatıcılar

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

Yuvalanmış koleksiyon Initializersaynı şekilde davranır:

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

Bu şu anlama gelir

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

new PersonSadece bir örneğini oluşturur Person, ancak Bookskoleksiyon hala null. Koleksiyon Initializersözdizimi için bir koleksiyon oluşturmaz p1.Books, yalnızca p1.Books.Add(...)ifadelere çevrilir .

Dizi

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

Dizi Elemanları

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.

Pürüzlü Diziler

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.

Toplama / Liste / Sözlük

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

Aralık Değişkeni (Dolaylı / Ertelenmiş)

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.

Etkinlikler

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. 

kamu sınıfı Form1 {özel Müşteri müşterisi;

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

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

}

Bu, alanların alt çizgi ile önek konulması kuralına uyularak çözülebilir:

    private Customer _customer;

ASP.NET Sayfa Yaşam döngüsü:

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

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

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

ASP.NET Oturum Değerleri

// 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 boş görünüm modelleri

Bir özelliğini başvuran istisnası oluşursa @Modelbir in ASP.NET MVC View, bunu anlamamız gerekir Model, eylem yönteminde belirlenen aldığında size returnbir görünümü. Denetleyicinizden boş bir model (veya model özelliği) döndürdüğünüzde, istisna görünümler eriştiğinde gerçekleşir:

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

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

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

WPF Denetimi Oluşturma Sırası ve Olaylar

WPFarama sırasında InitializeComponentgörsel ağaçta göründükleri sırayla kontroller oluşturulur . Bir NullReferenceExceptionyangın sırasında vs. olay işleyicileri, erken oluşturulan kontrollerin durumunda yükseltilecek InitializeComponentgeç oluşturulan denetimleri hangi referans.

Örneğin :

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

İşte comboBox1daha önce yaratılmış label1. Eğer comboBox1_SelectionChangedreferans `label1 girişimleri, henüz oluşturulmuş olmayacaktır.

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

XAML(Yani, daha label1önce listeleme comboBox1, tasarım felsefesi meselelerini görmezden gelme) içindeki bildirimlerin sırasını değiştirmek en azından NullReferenceExceptionburada çözecektir .

İle yayınla as

var myThing = someObject as Thing;

Bu bir atmaz, InvalidCastExceptionancak nulldöküm başarısız olduğunda (ve someObjectkendisi null olduğunda) a değerini döndürür . Öyleyse bunun farkında olun.

LINQ FirstOrDefault()veSingleOrDefault()

Düz sürümler First()ve Single()hiçbir şey olmadığında istisnalar atın. "OrDefault" sürümleri bu durumda null değerini döndürür. Öyleyse bunun farkında olun.

her biri için

foreachnull koleksiyonu yinelemeye çalıştığınızda atar. Genellikle nullkoleksiyonları döndüren yöntemlerden beklenmeyen sonuçlardan kaynaklanır.

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

Daha gerçekçi bir örnek - XML ​​belgesinden düğümleri seçin. Düğümler bulunmaz, ancak ilk hata ayıklama tüm özelliklerin geçerli olduğunu gösterirse atar:

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

Kaçınma Yolları

nullNull değerleri açıkça kontrol edin ve yok sayın.

Referansın bazen null olmasını bekliyorsanız, nullörnek üyelerine erişmeden önce referansın olup olmadığını kontrol edebilirsiniz :

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

nullVarsayılan değeri açıkça kontrol edin ve sağlayın.

Bir örnek döndürmeyi beklediğiniz yöntemler null, örneğin aranan nesne bulunamadığında dönebilir . Bu durumda varsayılan bir değer döndürmeyi seçebilirsiniz:

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

nullYöntem çağrılarından açıkça kontrol edin ve özel bir istisna atın.

Ayrıca, yalnızca arama kodunda yakalamak için özel bir istisna atayabilirsiniz:

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

Kullanım Debug.Assertdeğeri olmamalıdır eğer nullsorun daha erken durum oluşur daha yakalamak için.

Geliştirme sırasında bir yöntemin belki de geri dönebileceğini null, ancak asla geri dönmemesi gerektiğini bildiğinizde Debug.Assert(), gerçekleştiğinde mümkün olan en kısa sürede kırmak için kullanabilirsiniz :

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

Bu kontrol sürüm derlemenizde bitmeyecek olsa da, sürümde çalışma modundayken NullReferenceExceptiontekrar atmasına neden olur book == null.

Değer türlerinde oldukları zaman varsayılan bir değer sağlamak GetValueOrDefault()için kullanın .nullablenull

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

Boş birleştirme operatörü kullanın: ??[C #] veya If()[VB].

A nullile karşılaşıldığında varsayılan bir değer sağlama kısayolu :

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

Boş koşul operatörünü kullanın: ?.veya ?[x]diziler için (C # 6 ve VB.NET 14'te bulunur):

Buna bazen güvenli navigasyon veya Elvis (şeklinden sonra) operatörü de denir. Operatörün sol tarafındaki ifade null ise, sağ taraf değerlendirilmez ve bunun yerine null döndürülür. Bu, şu gibi durumlar anlamına gelir:

var title = person.Title.ToUpper();

Kişinin bir başlığı yoksa, ToUppernull değeri olan bir özelliği çağırmaya çalıştığı için bu bir istisna atar .

İçinde C# 5ve altında, bu ile korunabilir:

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

Şimdi istisna atmak yerine title değişkeni null olur. C # 6 bunun için daha kısa bir sözdizimi sunar:

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

Bu başlık değişkenin neden olacaktır nullve arama için ToUppereğer yapılmaması person.Titleolduğunu null.

Elbette, varsayılan bir değer sağlamak için halatitle null değerini kontrol etmeniz veya null koşul operatörünü (null birleştirme operatörü ( ??) ile birlikte kullanmanız gerekir :

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

Aynı şekilde, diziler için ?[i]aşağıdaki gibi kullanabilirsiniz :

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

Bu, aşağıdakileri yapacaktır: myIntArraynull ise, ifade null değerini döndürür ve güvenle denetleyebilirsiniz. Bir dizi içeriyorsa: elem = myIntArray[i];ile aynı işlemi yapar ve i<sup>th</sup>öğeyi döndürür .

Boş bağlam kullan (C # 8'de bulunur):

Burada tanıtılan C# 8null bağlamın ve null olabilecek referans türleri değişkenler üzerinde statik analiz yapar ve bir değer potansiyel olarak null veya null olarak ayarlanmışsa derleyici uyarısı sağlar. Null edilebilir başvuru türleri, türlerin açıkça boş olmasına izin verilir.

Null olabilecek ek açıklama bağlamı ve nullable uyarı bağlamı, dosyanızdaki Nullableöğeyi kullanan bir proje için ayarlanabilir csproj. Bu öğe, derleyicinin türlerin geçersizliğini ve hangi uyarıların üretileceğini nasıl yorumlayacağını yapılandırır. Geçerli ayarlar:

  • enable: Null olabilecek ek açıklama içeriği etkinleştirildi. Null olabilecek uyarı içeriği etkinleştirildi. Bir başvuru türünün değişkenleri, örneğin dize, boş bırakılamaz. Tüm nullabilite uyarıları etkindir.
  • devre dışı: Null olabilecek ek açıklama içeriği devre dışı. Null olabilecek uyarı içeriği devre dışı. Bir başvuru türünün değişkenleri, tıpkı C # 'ın önceki sürümlerinde olduğu gibi belirsizdir. Tüm nullabilite uyarıları devre dışıdır.
  • safeonly: Null olabilecek ek açıklama içeriği etkinleştirildi. Sıfırlanabilir uyarı içeriği güvenli bir şekilde. Referans türündeki değişkenler null değerine sahip değildir. Tüm güvenlik açıkları uyarıları etkindir.
  • uyarılar: Null olabilecek ek açıklama içeriği devre dışı. Null olabilecek uyarı içeriği etkinleştirildi. Referans tipindeki değişkenler açıktır. Tüm nullabilite uyarıları etkindir.
  • safeonlywarnings: Null olabilecek ek açıklama içeriği devre dışı. Sıfırlanabilir uyarı içeriği güvenli bir şekilde. Referans tipindeki değişkenler açıktır. Tüm güvenlik açıkları uyarıları etkindir.

Null olabilecek değer türleriyle aynı sözdizimi kullanılarak null olabilecek bir başvuru türü not edilir: ?değişkenin türüne a eklenir.

Yineleyicilerin null dereflerin hata ayıklaması ve düzeltilmesi için özel teknikler

C#"yineleyici blokları" (diğer bazı popüler dillerde "jeneratörler" olarak adlandırılır) destekler. Boş dereference istisnaları, ertelenmiş yürütme nedeniyle yineleyici bloklarında hata ayıklamak için özellikle zor olabilir:

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

Eğer whateversonuç nullo MakeFrobzaman atar. Şimdi, yapılacak doğru şeyin bu olduğunu düşünebilirsiniz:

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

Bu neden yanlış? Yineleyici blok aslında olmadığından çalıştırmak kadar foreach! Çağırma çağrısı , yinelendiğinde yineleyici bloğunu çalıştıracak GetFrobsbir nesne döndürür .

Bu şekilde null bir denetim yazarak null dereference'ı önlersiniz, ancak null argüman istisnasını yineleme noktasına değil, çağrının noktasına taşırsınız ve bu hata ayıklamak çok kafa karıştırıcıdır .

Doğru düzeltme:

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

Yani, yineleyici blok mantığına sahip özel bir yardımcı yöntem ve null kontrolü yapan ve yineleyiciyi döndüren bir ortak yüzey yöntemi yapın. Şimdi GetFrobsçağrıldığında, null kontrolü hemen gerçekleşir ve ardından GetFrobsForRealdizi yinelendiğinde yürütülür.

LINQNesneler için referans kaynağını incelerseniz, bu tekniğin baştan sona kullanıldığını göreceksiniz. Yazmak biraz daha karmaşıktır, ancak hata ayıklama hata hatalarını çok daha kolay hale getirir. Kodunuzu, yazarın rahatlığı için değil, arayanın rahatlığı için optimize edin .

Güvenli olmayan kodda null dereferences hakkında bir not

C#bellek güvenliğini ve tip güvenliğini sağlayan normal emniyet mekanizmaları uygulanmadığından, adından da anlaşılacağı üzere, "güvensiz" bir moda sahiptir. Belleğin nasıl çalıştığını tam ve derin bir şekilde anlamadığınız sürece güvenli olmayan kod yazmamalısınız .

Güvenli olmayan modda, iki önemli gerçeğin farkında olmalısınız:

  • bir boş dereferencing işaretçi boş çözümleyecek aynı durum meydana başvuru
  • geçersiz bir boş olmayan işaretçiyi kaldırma olabilir , bazı durumlarda bu durum üretmek

Bunun nedenini anlamak için, .NET'in ilk olarak nasıl boş dereference istisnaları ürettiğini anlamaya yardımcı olur. (Bu ayrıntılar Windows üzerinde çalışan .NET için geçerlidir; diğer işletim sistemleri benzer mekanizmalar kullanır.)

Bellek sanallaştırılır Windows; her işlem, işletim sistemi tarafından izlenen birçok "sayfa" belleğin sanal bellek alanına sahip olur. Belleğin her sayfasında, nasıl kullanılabileceğini belirleyen işaretler bulunur: okuma, yazma, yürütme vb. En düşük sayfa "herhangi bir şekilde kullanılıyorsa hata üret" olarak işaretlenir.

Hem null işaretçi hem de null referans C#dahili olarak sıfır sayısı olarak temsil edilir ve bu nedenle karşılık gelen bellek deposuna atılmak için yapılan her girişim, işletim sisteminde bir hataya neden olur. Sonra .NET çalışma zamanı bu hatayı algılar ve null dereference istisnasına dönüştürür.

Bu nedenle, hem boş gösterici hem de boş bir başvurunun kayıttan çıkarılması aynı istisnayı oluşturur.

İkinci nokta ne olacak? Dereferencing herhangi bir sanal bellek düşük sayfasında düşüyor geçersiz işaretçi aynı işletim sistemi hatası ve böylece aynı duruma neden olur.

Bu neden mantıklı? Diyelim ki iki int içeren bir yapımız ve null değerine eşit yönetilmeyen bir işaretçi var. Eğer yapıdaki ikinci int'den vazgeçmeye CLRçalışırsak, sıfır noktasına depolamaya erişmeye çalışmaz; depolama alanına dördüncü konumdan erişir. Ama mantıklı olarak bu bir boş dereference çünkü bu adrese null üzerinden ulaşıyoruz.

Güvenli olmayan kodla çalışıyorsanız ve boş bir kural dışı durum istisnası alıyorsanız, rahatsız edici işaretçinin boş olması gerekmediğini unutmayın. En alt sayfada herhangi bir yer olabilir ve bu istisna üretilecektir.


55
Belki bu aptalca bir yorum ama bu problemden kaçınmanın ilk ve en iyi yolu nesneyi başlatmak değil mi? Bu hata oluşursa benim için genellikle dizi elemanı gibi bir şey başlatmayı unuttum çünkü. Nesneyi null olarak tanımlamak ve sonra başvurmak çok daha az yaygın olduğunu düşünüyorum. Belki açıklamaya bitişik her sorunu çözmek için yol verin. Hala iyi bir gönderi.
JPK

30
Nesne yoksa, daha çok bir yöntem veya özellikten döndürülen değer varsa ne olur?
John Saunders

6
Kitap / yazar örneği biraz garip .... Bu nasıl derleniyor? Intellisense nasıl çalışır? Bu nedir ben

5
@Will: Son düzenlemem yardımcı oluyor mu? Değilse, lütfen sorun olarak gördükleriniz konusunda daha açık olun.
John Saunders

6
@JohnSaunders Oh, hayır, üzgünüm, bunun nesne başlatıcı sürümünü kastediyorum. new Book { Author = { Age = 45 } };İçsel başlatma nasıl ... İçsel initin işe yarayacağı bir durum düşünemiyorum, ancak derler ve zekâ çalışır ... Yapılar olmadığı sürece?

311

NullReference Özel Durumu - Visual Basic

NullReference Exceptionİçin Visual Basic içinde birinden farklı değil C # . Sonuçta, her ikisi de kullandıkları .NET Framework'te tanımlanan aynı özel durumu bildiriyorlar. Visual Basic'e özgü nedenler nadirdir (belki de sadece bir tane).

Bu yanıt Visual Basic terimlerini, sözdizimini ve bağlamı kullanacaktır. Kullanılan örnekler çok sayıda geçmiş Stack Overflow sorusundan gelmektedir. Bu, yazılarda sıklıkla görülen durum türlerini kullanarak alaka düzeyini en üst düzeye çıkarmaktır . İhtiyaç duyanlar için biraz daha açıklama da yapılır. Sizinkine benzer bir örneği olduğu çok muhtemeldir burada listelenen.

Not:

  1. Bu kavram tabanlı: projenize yapıştırmanız için bir kod yok. Neye NullReferenceException(NRE) neyin neden olduğunu, nasıl bulunacağını, nasıl düzeltileceğini ve nasıl önleneceğini anlamanıza yardımcı olmak için tasarlanmıştır . Bir NRE'ye birçok yol neden olabilir, bu yüzden bunun tek karşılaşmanız olma ihtimali düşüktür.
  2. Örnekler (Yığın Taşması gönderilerinden) her zaman bir şey yapmanın en iyi yolunu göstermez.
  3. Tipik olarak, en basit çözüm kullanılır.

Temel Anlam

"Nesne bir Nesne örneğine ayarlanmadı" iletisi , başlatılmamış bir nesneyi kullanmaya çalıştığınız anlamına gelir. Bu aşağıdakilerden birine dayanır:

  • Kodunuz bir nesne değişkeni bildirdi , ancak onu başlatmadı (bir örnek oluşturun veya ' örnekleyin ')
  • Kodunuzun bir nesneyi başlattığını varsaydığı bir şey,
  • Muhtemelen, diğer kod kullanılmakta olan bir nesneyi vaktinden önce geçersiz kılmıştır

Nedeni Bulma

Sorun bir nesne referansı olduğu için Nothing, cevap hangisini bulmak için onları incelemektir. Ardından neden başlatılmadığını belirleyin. Fareyi çeşitli değişkenlerin üzerinde tutun ve Visual Studio (VS) değerlerini gösterecektir - suçlu olacak Nothing.

IDE hata ayıklama ekranı

Ayrıca, Try / Catch bloklarını, özellikle Catch bloğunda hiçbir şeyin olmadığı kodları da ilgili koddan kaldırmalısınız. Bu, kodunuz olan bir nesneyi kullanmaya çalıştığında çökmesine neden olur Nothing. Bu ne istediğiniz o kesin belirleyecektir çünkü konumu sorunu ve bunu neden nesneyi tanımlamak için izin verir.

Görüntülenen MsgBoxYakalama'daki A Error while...çok yardımcı olacaktır. Bu yöntem aynı zamanda çok kötü Yığın Taşması sorularına da yol açar , çünkü gerçek istisnayı, dahil olan nesneyi veya hatta gerçekleştiği kod satırını tanımlayamazsınız.

Nesnelerinizi incelemek için Locals Window( Hata Ayıkla -> Windows -> Yerel Ayarlar ) öğesini de kullanabilirsiniz .

Sorunun ne olduğunu ve nerede olduğunu öğrendikten sonra, yeni bir soru göndermekten genellikle düzeltilmesi oldukça kolaydır.

Ayrıca bakınız:

Örnekler ve Çözümler

Sınıf Nesneleri / Örnek Oluşturma

Dim reg As CashRegister
...
TextBox1.Text = reg.Amount         ' NRE

Sorun, Dimbir CashRegister nesnesi oluşturmamasıdır ; yalnızca regbu Tür adlı bir değişkeni bildirir . Bir nesne değişkenini bildirmek ve bir örnek oluşturmak iki farklı şeydir.

çare

NewOperatör sıklıkla beyan zaman örneğini oluşturmak için kullanılabilir:

Dim reg As New CashRegister        ' [New] creates instance, invokes the constructor

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

Yalnızca daha sonra örneği oluşturmak uygun olduğunda:

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

Not: Do not kullanmak Dimyapıcısı (dahil olmak üzere bir prosedür tekrar Sub New):

Private reg As CashRegister
'...

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

Bu, yalnızca bu bağlamda (alt) bulunan yerel bir değişken oluşturur reg. Diğer her yerde kullanacağınız regmodül seviyeli değişken Scopekalır Nothing.

İşlecin eksik Newolması,NullReference Exceptions incelenen Yığın Taşması sorularında görülen 1 numaralı nedendir .

Visual Basic işlemi kullanarak tekrar tekrar netleştirmeye çalışır New: NewOperator kullanarak yeni bir nesne oluşturur ve Sub Newnesnenin başka bir başlatma gerçekleştirebilirsiniz - yapıcı - çağırır .

Açık olmak gerekirse, Dim(veya Private) yalnızca bir değişkeni ve değişkenini bildirirType . Kapsam Bu, tüm modülü / sınıf için var olan ya da bir prosedür yerel olup - - değişken belirlenir burada bu ilan edilir. Private | Friend | Publicerişim düzeyini değil, tanımlar Kapsam .

Daha fazla bilgi için, bkz:


Diziler

Diziler de somutlaştırılmalıdır:

Private arr as String()

Bu dizi yalnızca bildirildi, oluşturulmadı. Bir diziyi başlatmanın birkaç yolu vardır:

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

Not: Değişmez kullanarak yerel bir dizi başlatma ve zaman VS 2010 ile başlayarak, Option Infer, As <Type>ve Newelemanlar isteğe bağlıdır:

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}

Veri türü ve dizi boyutu atanan verilerden çıkarılır. Sınıf / Modül düzeyinde bildirimleri hala gerektirir As <Type>ile Option Strict:

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

Örnek: Sınıf nesneleri dizisi

Dim arrFoo(5) As Foo

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

Dizi oluşturuldu, ancak içindeki Foonesneler oluşturulmadı .

çare

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

Bir List(Of T)irade kullanmak, geçerli bir nesnesi olmayan bir öğeye sahip olmayı oldukça zorlaştıracaktır:

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

Daha fazla bilgi için, bkz:


Listeler ve Koleksiyonlar

Çok sayıda çeşidi olan Listeler, Sözlük vb. .NET koleksiyonlarının da başlatılması veya oluşturulması gerekir.

Private myList As List(Of String)
..
myList.Add("ziggy")           ' NullReference

Aynı nedenden ötürü aynı istisnayı elde edersiniz - myListsadece beyan edildi, ancak hiçbir örnek oluşturulmadı. Çözüm aynıdır:

myList = New List(Of String)

' Or create an instance when declared:
Private myList As New List(Of String)

Ortak bir gözetim, koleksiyon kullanan bir sınıftır 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

Her iki yordam da bir NRE ile sonuçlanır, çünkü barListyalnızca bildirilir, somutlaştırılmaz. Örneği oluşturmak Fooaynı zamanda dahili örneği de oluşturmaz barList. Bunu yapıcıda yapmak niyetinde olabilir:

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

Daha önce olduğu gibi, bu yanlış:

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

Daha fazla bilgi için, bkz. List(Of T)Sınıf .


Veri Sağlayıcı Nesneleri

Bir NullReference için veritabanları hediyelerle birçok fırsat Çalışma sayıda nesne (olabilir çünkü Command, Connection, Transaction, Dataset, DataTable, DataRowsaynı anda kullanımda ....). Not: Hangi veri sağlayıcıyı kullandığınız önemli değildir - MySQL, SQL Server, OleDB, vb. - kavramlar aynıdır.

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

Daha önce olduğu gibi, dsVeri Kümesi nesnesi bildirildi, ancak hiçbir zaman bir örnek oluşturulmadı. Bu DataAdapteristek mevcut DataSetolanı doldurur, bir tane oluşturmaz. Bu durumda, dsyerel bir değişken olduğundan IDE bunun olabileceği konusunda sizi uyarır :

img

Modül / sınıf düzeyinde bir değişken olarak bildirildiğinde, durumun göründüğü gibi con, derleyici, nesnenin bir yukarı akış yordamı tarafından oluşturulup oluşturulmadığını bilemez. Uyarıları dikkate almayın.

çare

Dim ds As New DataSet

ÖRNEK 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)

Bir yazım hatası burada bir sorun: Employeesvs Employee. Hiçbir Orada edildi DataTablebir nedenle, "Çalışan" yaratılmış adlı NullReferenceExceptionsonuçlar ulaşmaya çalışıyorsunuz. Başka bir potansiyel sorun, ItemsSQL bir WHERE yantümcesi içerdiğinde böyle olmayacağını varsayar .

çare

Bu bir tablo kullandığından, kullanmak Tables(0)yazım hatalarını önler. İnceleme Rows.Countayrıca yardımcı olabilir:

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

FillRowsetkilenenlerin sayısını döndüren ve test edilebilen bir işlevdir :

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

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

DataAdapterSağlayacaktır TableNamesönceki örnekte görüldüğü gibi, ancak, SQL veya veritabanı tablosundan ayrıştırma isimleri yapar değil. Sonuç olarak, ds.Tables("TICKET_RESERVATION")varolmayan bir tabloya başvurur.

Çözüm endeksine göre tablo başvurusu, aynıdır:

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

Ayrıca bkz . DataTable Sınıfı .


Nesne Yolları / İç İçe

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

Kod sadece Itemsher ikisinde de test ediyor myFoove Barhiçbir şey olmayabilir. İlaç , bir anda tüm zincirli veya nesne, bir yolunu test etmektir:

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

AndAlsoönemli. İlk Falsekoşulla karşılaşıldığında sonraki testler yapılmayacaktır . Bu, kodun nesnelere / nesnelere her seferinde bir 'seviye' güvenli bir şekilde 'delmesini' sağlar ve myFoo.Baryalnızca sonra (ve) myFoogeçerli olduğu belirlenir. Karmaşık nesneleri kodlarken nesne zincirleri veya yolları oldukça uzun sürebilir:

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

Bir nullnesnenin 'akış aşağısına' herhangi bir şey referans vermek mümkün değildir . Bu aynı zamanda kontroller için de geçerlidir:

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

Burada, myWebBrowserya Documentda Hiçbir şey olabilir ya da formfld1öğe olmayabilir.


UI Denetimleri

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)

Diğer şeylerin yanı sıra, bu kod kullanıcının bir veya daha fazla UI kontrolünde bir şey seçmemiş olabileceğini öngörmez. ListBox1.SelectedItemolabilir Nothing, bu nedenle ListBox1.SelectedItem.ToStringbir NRE ile sonuçlanacaktır.

çare

Kullanmadan önce verileri doğrulayın (ayrıca Option Strictve SQL parametrelerini de kullanın ):

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

Alternatif olarak, (ComboBox5.SelectedItem IsNot Nothing) AndAlso...


Visual Basic Formları

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

Bu, bir NRE elde etmenin oldukça yaygın bir yoludur. C # 'da, nasıl kodlandığına bağlı olarak, IDE Controlsgeçerli bağlamda bulunmadığını veya "statik olmayan üyeye başvuramayacağını" bildirecektir . Yani, bir dereceye kadar, bu sadece bir VB durumudur. Aynı zamanda karmaşıktır, çünkü bir başarısızlık kaskatına neden olabilir.

Diziler ve koleksiyonlar bu şekilde başlatılamaz. Bu başlatma kodu , yapıcı veya öğesini oluşturmadan önce çalışır . Sonuç olarak:FormControls

  • Listeler ve Koleksiyon boş olacak
  • Dizi, Hiçbir Şey öğesinin beş öğesini içerecektir
  • somevarHiçbir şey bir sahip olmadığı için atama acil NRE neden olacaktır .Textözelliği

Dizi öğelerine daha sonra başvurmak bir NRE ile sonuçlanır. Bu in yaparsanız Form_Loadnedeniyle garip bir hatadan, IDE olmayabilir o olur istisna raporu. Kodunuz diziyi kullanmaya çalıştığında istisna daha sonra açılır . Bu "sessiz istisna" bu yayında detaylandırılmıştır . Bizim amacımız için anahtar, bir form ( Sub Newveya Form Loadolay) oluştururken felaket bir şey olduğunda , istisnalar bildirilmeyebilir, kod prosedürden çıkar ve sadece formu görüntüler.

NRE'den sonra etkinliğinizde Sub Newveya Form Loadetkinliğinizde başka hiçbir kod çalışmadığından, pek çok başka şey başlatılmadan bırakılabilir.

Sub Form_Load(..._
   '...
   Dim name As String = NameBoxes(2).Text        ' NRE
   ' ...
   ' More code (which will likely not be executed)
   ' ...
End Sub

Bunun, bunları yasadışı oldukları yerlerde yapan tüm kontrol ve bileşen referansları için geçerli olduğunu unutmayın :

Public Class Form1

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

Kısmi Çözüm

VB bir uyarı sağlamaz meraklı olmakla çare olmaktır beyan formu düzeyinde kapları, ancak başlatmak kontrolleri yaparken form yük olay işleyicisi bunları yapmak vardır. Bu, Sub Newkodunuz InitializeComponentçağrıdan sonra olduğu sürece yapılabilir :

' 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

Dizi kodu henüz orman dışında olmayabilir. Bir konteyner kontrolünde olan kontroller (a GroupBoxveya gibi Panel) içinde bulunmaz Me.Controls; bu Panel veya GroupBox öğesinin Kontroller koleksiyonunda olacaklardır. Kontrol adı yanlış yazıldığında ( "TeStBox2") da bir kontrol döndürülmez . Bu gibi durumlarda, Nothingyine bu dizi öğelerinde saklanır ve referans vermeye çalıştığınızda bir NRE oluşur.

Ne aradığınızı bildiğiniz için bunları bulmak kolay olmalıdır: VS size yollarınızın hatasını gösterir

"Button2", Panel

çare

Formun Controlskoleksiyonunu kullanarak ada göre dolaylı başvurular yerine , denetim başvurusunu kullanın:

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

İşlev Geri Dönen Hiçbir Şey

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

Bu, IDE'nin ' tüm yolların bir değer döndürmediği ve bir NullReferenceExceptionsonucun ortaya çıkabileceği ' konusunda sizi uyaracağı bir durumdur . Sen değiştirerek, uyarıyı bastırmak Exit Functionile Return Nothing, ama bu sorunu çözmez. Ne zaman dönüşü kullanmaya çalışan herhangi bir şey someCondition = FalseNRE ile sonuçlanır:

bList = myFoo.BarList()
For Each b As Bar in bList      ' EXCEPTION
      ...

çare

İşlevdeki Exit Functionile değiştirin Return bList. Bir dönersek boş List dönen aynı şey değildir Nothing. Döndürülen bir nesnenin olma şansı varsa Nothing, kullanmadan önce test edin:

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

Kötü Uygulanan Deneme / Yakalama

Kötü uygulanan Try / Catch, sorunun nerede olduğunu gizleyebilir ve yenileriyle sonuçlanabilir:

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

Bu, beklendiği gibi yaratılmayan bir nesnenin örneğidir, ancak boş bir nesnenin karşı kullanışlılığını da gösterir Catch.

SQL'de ('mailaddress' den sonra) 'da bir istisna ile sonuçlanan fazladan bir virgül vardır .ExecuteReader. CatchHiçbir şey yapmadan sonra, Finallytemizlemeyi yapmaya çalışır, ancak Closeboş bir DataReadernesne olamayacağınız için yepyeni bir NullReferenceExceptionsonuç elde edersiniz .

Boş bir Catchblok şeytanın oyun alanıdır. Bu OP, neden Finallyblokta bir NRE aldığını şaşırttı . Diğer durumlarda, boş Catchbir şey daha aşağı akış yönünde başka bir şeyle sonuçlanabilir ve sorun için yanlış yere yanlış şeylere bakmak için zaman harcamanıza neden olabilir. (Yukarıda açıklanan "sessiz istisna" aynı eğlence değerini sağlar.)

çare

Boş Try / Catch blokları kullanmayın - kodun çökmesine izin verin, böylece a) nedenini tanımlayın b) konumu belirleyin ve c) uygun bir çözüm uygulayın. Try / Catch blokları, bunları düzeltmek için benzersiz nitelikteki kişiden istisnaları gizlemek için tasarlanmamıştır - geliştirici.


DBNull, Hiçbir Şey ile aynı değil

For Each row As DataGridViewRow In dgvPlanning.Rows
    If Not IsDBNull(row.Cells(0).Value) Then
        ...

IsDBNullBir IF_FUNCTION testi için kullanılan değer eşittir System.DBNull: MSDN:

System.DBNull değeri, Object'in eksik veya var olmayan verileri temsil ettiğini gösterir. DBNull, bir değişkenin henüz başlatılmadığını gösteren Hiçbir Şey ile aynı değildir.

çare

If row.Cells(0) IsNot Nothing Then ...

Daha önce olduğu gibi, Hiçbir şey için, ardından belirli bir değer için test edebilirsiniz:

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

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

FirstOrDefaultNothingreferans türleri için olan ve asla DBNull: ilk öğeyi veya varsayılan değeri döndürür :

If getFoo IsNot Nothing Then...

Kontroller

Dim chk As CheckBox

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

A CheckBoxile chkNamebulunamazsa (veya a'da mevcutsa GroupBox), chkHiçbir şey olmaz ve herhangi bir özelliğe başvurmaya çalışmak istisnaya neden olur.

çare

If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...

DataGridView

DGV'nin periyodik olarak görülen birkaç tuhaflığı var:

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"

Varsa dgvBooks, AutoGenerateColumns = Truesütunları oluşturur, ancak bunları adlandırmaz, bu nedenle yukarıdaki kod, ada göre başvurduğunda başarısız olur.

çare

Sütunları manuel olarak adlandırın veya dizine göre başvuru yapın:

dgvBooks.Columns(0).Visible = True

Örnek 2 - NewRow'a dikkat edin

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

When DataGridViewsahip AllowUserToAddRowsolarak True(varsayılan), Cellsaltta işlenmemiş / yeni satır tümünü içerir Nothing. İçeriği (ör. ToString) Kullanma girişimlerinin çoğu NRE ile sonuçlanır.

çare

Bir For/Eachdöngü kullanın ve IsNewRowson satır olup olmadığını belirlemek için özelliği test edin . Bu AllowUserToAddRowsdoğru olsun ya da olmasın çalışır :

For Each r As DataGridViewRow in myDGV.Rows
    If r.IsNewRow = False Then
         ' ok to use this row

Bir For ndöngü kullanıyorsanız , satır sayısını değiştirin veya true Exit Forolduğunda kullanın IsNewRow.


Ayarlarım (StringCollection)

Belirli koşullar altında, bir öğeyi kullanmaya çalışıyor My.Settingsbir olan StringCollectionbir NullReference içinde bunu kullanmak ilk defa sonuçlanabilir. Çözüm aynı, ancak belli değil. Düşünmek:

My.Settings.FooBars.Add("ziggy")         ' foobars is a string collection

VB sizin için Ayarlar'ı yönettiği için koleksiyonun başlatılmasını beklemek mantıklıdır. Ancak, koleksiyona daha önce bir başlangıç ​​girdisi eklediyseniz (Ayarlar düzenleyicisinde). Bir öğe eklendiğinde koleksiyon (görünüşte) başlatıldığından, eklenecek NothingAyarlar düzenleyicisinde hiçbir öğe olmadığında kalır .

çare

LoadGerekirse / gerektiğinde, formun olay işleyicisindeki ayarlar koleksiyonunu başlatın :

If My.Settings.FooBars Is Nothing Then
    My.Settings.FooBars = New System.Collections.Specialized.StringCollection
End If

Genellikle, Settingskoleksiyonun yalnızca uygulama ilk çalıştırıldığında başlatılması gerekir. Alternatif bir çözüm, Project -> Ayarlar | FooBars , projeyi kaydedin, sonra sahte değeri kaldırın.


Anahtar noktaları

Muhtemelen Newoperatörü unuttun .

veya

Başlatılan bir nesneyi kodunuza döndürmek için sorunsuz bir şekilde gerçekleştireceğinizi varsaydığınız bir şey olmadı.

Derleyici uyarılarını (hiç) dikkate almayın ve Option Strict On(her zaman) kullanmayın .


MSDN NullReference Özel Durumu


226

Başka bir senaryo, null bir nesneyi bir değer türüne attığınız durumdur . Örneğin, aşağıdaki kod:

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

Bu bir atacağım NullReferenceExceptiondöküm üzerinde. Yukarıdaki örnekte oldukça açık görünmektedir, ancak bu, null nesnesinin sahip olmadığınız bazı kodlardan döndürüldüğü ve dökümün örneğin bazı otomatik sistem tarafından oluşturulduğu daha "geç bağlayıcı" karmaşık senaryolarda olabilir.

Bunun bir örneği bu basit ASP.NET bağlama parçasını Takvim denetimi ile:

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

Burada, SelectedDatebir - bir özellik aslında DateTimetip - ait CalendarWeb Kontrol türü ve mükemmel bir şey return null olabilir bağlayıcı. Örtülü ASP.NET Generator yukarıdaki döküm koduna eşdeğer olacak bir kod parçası oluşturur. Ve bu NullReferenceExceptionince bir derleyen ASP.NET oluşturulan kod yatıyor çünkü, bu oldukça zor bir nokta yükseltir ...


7
Büyük yakalamak. Kaçınmanın tek yolu:DateTime x = (DateTime) o as DateTime? ?? defaultValue;
Serge Shultz

159

Bu, söz konusu değişkenin hiçbir şeye işaret etmediği anlamına gelir. Ben böyle üretebilir:

SqlConnection connection = null;
connection.Open();

Bu hatayı atacak çünkü " connection" değişkenini beyan ederken , hiçbir şeye işaret etmiyor. " Open" Adlı üyeyi aramaya çalıştığımda , çözümlemesi için bir referans yok ve hatayı atacak.

Bu hatayı önlemek için:

  1. Onlarla herhangi bir şey yapmaya çalışmadan önce her zaman nesnelerinizi başlatın.
  2. Nesnenin boş olup olmadığından emin değilseniz, ile kontrol edin object == null.

JetBrains 'Resharper aracı, kodunuzda bir boş başvuru hatası olasılığı bulunan her yeri tanımlar ve boş bir denetim gerçekleştirmenize olanak tanır. Bu hata bir numaralı hata kaynağıdır, IMHO.


3
JetBrains 'Resharper aracı, kodunuzda boş bir başvuru hatası olasılığı bulunan her yeri belirler. Bu yanlış. Bu algılama olmadan bir çözüm var, ancak kod bazen istisna sonuçlanır. Multithreading söz konusu olduğunda, bazen en azından onlar tarafından algılanamayacağından şüpheleniyorum, ancak daha fazla yorum yapamıyorum çünkü henüz hatanın yerini tanımlayamadım.
j riv

Ancak NullReferenceException HttpContext.Current.Responce.Clear () öğesinin kullanılmasında nasıl çözülür. Yukarıdaki çözümlerden herhangi biri tarafından çözülmüyor. çünkü HttpContext nesnesi nesnesini oluştururken bir hata geliyor, "Erişilebilir 'Yeni' bu argüman sayısını kabul etmediğinden aşırı yük çözünürlüğü başarısız oldu.
Sunny Sandeep

157

Kodunuzun, null olarak ayarlanmış bir nesne başvuru değişkeni kullandığı (yani, gerçek bir nesne örneğine başvurmadığı) anlamına gelir.

Hatayı önlemek için null olabilecek nesneler kullanılmadan önce null için test edilmelidir.

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

Senaryoya bakılmaksızın, nedenin .NET'te her zaman aynı olduğunu unutmayın:

Değeri Nothing/ olan bir başvuru değişkeni kullanmaya çalışıyorsunuz null. Değer, başvuru değişkeni için Nothing/ olduğunda null, bu aslında yığın üzerinde var olan herhangi bir nesnenin örneğine bir başvuru tutmadığı anlamına gelir.

Ya değişkene atanan değerin bir örneğini oluşturdu asla değişkene şey atanan asla veya değişkeni ayarlamak için eşit Nothing/ nullmanuel veya değişkeni ayarlamak bir işlevi olarak adlandırılan Nothing/ ' nullsenin için.


87

Atılan bu istisnanın bir örneği: Bir şeyi kontrol etmeye çalıştığınızda, bu boştur.

Örneğin:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

.NET çalışma zamanı, başlatılmamış bir şey üzerinde bir eylem gerçekleştirmeye çalıştığınızda (örn. Yukarıdaki kod) bir NullReferenceException kurar.

Bir yöntem kendisine iletilen şeyin null olmadığını beklerse, genellikle bir savunma ölçüsü olarak atılan bir ArgumentNullException özelliğine kıyasla.

Daha fazla bilgi için C # NullReferenceException ve Null Parametreleri bulunur .


87

Güncelleme C # 8.0, 2019: Null olabilecek referans türleri

C # 8.0 nullable referans türleri ve nullable referans türleri sunar . Bu nedenle, NullReferenceException özel durumundan kaçınmak için yalnızca boş değerli başvuru türlerinin denetlenmesi gerekir .


Bir başvuru türünü başlatmadıysanız ve özelliklerinden birini ayarlamak veya okumak istiyorsanız, bir NullReferenceException kurar .

Misal:

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

Değişkenin boş olup olmadığını kontrol ederek bunu önleyebilirsiniz:

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

NullReferenceException özelliğinin neden atıldığını tam olarak anlamak için, değer türleri ile [başvuru türleri] arasındaki farkı bilmek önemlidir [3].

Uğraştığın Yani, değer türleri , NullReferenceExceptions olabilir değil oluşabilir. Referans türleriyle uğraşırken uyanık olmanız gerekir !

Yalnızca adın önerdiği gibi referans türleri referansları tutabilir veya tam anlamıyla hiçbir şeye (veya 'null') işaret edebilir. Oysa değer türleri her zaman bir değer içerir.

Referans türleri (bunlar kontrol edilmelidir):

  • dinamik
  • nesne
  • sicim

Değer türleri (bunları göz ardı edebilirsiniz):

  • Sayısal tipler
  • İntegral çeşitleri
  • Kayan nokta türleri
  • ondalık
  • bool
  • Kullanıcı tanımlı yapılar

6
-1: soru "NullReferenceException nedir" olduğundan, değer türleri ilgili değildir.
John Saunders

21
@John Saunders: Katılmıyorum. Bir yazılım geliştiricisi olarak değer ve referans türlerini ayırt edebilmek gerçekten önemlidir. aksi halde insanlar tamsayıların boş olup olmadığını kontrol ederler.
Fabian Bigler

5
Doğru, bu soru bağlamında değil.
John Saunders

4
İpucu için teşekkürler. Biraz geliştirdim ve üstüne bir örnek ekledim. Referans ve Değer Türlerinden bahsetmenin hala yararlı olduğunu düşünüyorum.
Fabian Bigler

5
Sorunun bir referans türünü önceden varsaydığı için diğer cevaplarda bulunmayan hiçbir şey eklemediğinizi düşünüyorum.
John Saunders

78

NullReferenceExceptionsOlabilecek başka bir durum , asoperatörün (yanlış) kullanımıdır :

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

Burada Bookve Caruyumsuz türler; a Cardönüştürülemez / a dönüştürülemez Book. Bu yayın başarısız olduğunda asgeri döner null. Bundan mybooksonra kullanmak a NullReferenceException.

Genel olarak, bir döküm kullanmalısınız veya asaşağıdaki gibi:

Tür dönüşümünün her zaman başarılı olmasını bekliyorsanız (yani, nesnenin vaktinden önce ne olması gerektiğini biliyorsanız), bir döküm kullanmalısınız:

ComicBook cb = (ComicBook)specificBook;

Türden emin değilseniz, ancak belirli bir tür olarak kullanmayı denemek istiyorsanız , şunu kullanın as:

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

2
Bu çok şey olabilir unboxing bir değişken. UI öğesinin türünü değiştirdikten sonra olay işleyicilerinde sık sık oluyor, ancak arkadaki kodu güncellemeyi unuttum.
Brendan

65

Boş değer başvurusunu içeren nesneyi kullanıyorsunuz. Yani boş bir istisna veriyor. Örnekte dize değeri null ve uzunluğunu kontrol ederken kural dışı durum oluştu.

Misal:

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

İstisna hatası:

İşlenmeyen özel durum:

System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı. Program.Main () 'da


1
Ne kadar derin! Asla 'null' sabitini referans değeri olarak düşünmedim. Peki bu C # nasıl bir "NullPointer" ha? B / c C ++ 'da hatırladığım gibi, bir NPE, varsayılan değeri bu işleme atanmamış bir adres olan başlatılmamış bir işaretçiyi (yani, c # içinde ref tipi) kaydı silme işleminden kaynaklanabilir (birçok durumda bu 0 olur, özellikle C ++ ile otomatik başlatma yapan ve bununla birlikte OS - f'ye ait olan ve beeotch (daha sonra OS'nin işleminize saldırdığı sigkill'i yakalayın) sonraki sürümlerinde).
samis

64

İken Ne bir sebep NullReferenceExceptions ve yaklaşımları kaçınmak / düzeltmek diğer yanıtlar ele alınmıştır böyle bir istisna, birçok programcı henüz öğrenmemiş ne bağımsız nasıl olduğunu hata ayıklamak gelişimi sırasında bu tür istisnalar.

Visual Studio'da bu genellikle Visual Studio Hata Ayıklayıcısı sayesinde kolaydır .


İlk olarak, doğru hatanın yakalanacağından emin olun - bkz . VS2010'da 'System.NullReferenceException' öğesinin kesilmesine nasıl izin verebilirim? Not 1

Sonra Hata Ayıklama (F5) ile başlayın veya [VS Hata Ayıklayıcı] 'yı Çalıştırma İşlemine ekleyin . Bazen Debugger.Breakhata ayıklayıcıyı başlatmayı isteyecek kullanımı yararlı olabilir .

Şimdi, NullReferenceException özel durumu atıldığında (veya işlenmediğinde) hata ayıklayıcı, özel durumun oluştuğu satırda durur (yukarıda ayarlanan kuralı hatırlıyor musunuz?). Bazen hatanın fark edilmesi kolay olur.

Örneğin, aşağıdaki satırda özel duruma neden olabilecek tek kod myStringnull olarak değerlendirilir. Bu, İzleme Penceresine bakarak veya Anlık Pencerede ifadeleri çalıştırarak doğrulanabilir .

var x = myString.Trim();

Aşağıdakiler gibi daha gelişmiş durumlarda, str1null olup olmadığını veya null olup olmadığını belirlemek için ifadeleri incelemek için yukarıdaki tekniklerden birini (Watch veya Immediate Windows) kullanmanız gerekir str2.

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

İstisnanın atıldığı bir yere yerleştirildikten sonra , null değerin [yanlış] nereye yerleştirildiğini bulmak genellikle geriye doğru muhakeme yapmak önemsizdir -

İstisnanın nedenini anlamak için gereken zamanı ayırın. Boş ifadeler olup olmadığını kontrol edin. Bu tür boş ifadelere yol açmış olabilecek önceki ifadeleri inceleyin. Kesme noktaları ekleyin ve programa uygun şekilde adım atın . Hata ayıklayıcıyı kullanın.


1 Atışlarda Ara çok agresifse ve hata ayıklayıcı, .NET veya 3. taraf kitaplığındaki bir NPE'de durursa, yakalanan istisnaları sınırlamak için Kullanıcı İşlenmemiş Break kullanılabilir. Ayrıca, VS2012, etkinleştirmeyi de tavsiye ettiğim Just My Code'u sunar .

Just My Code etkinken hata ayıklama yapıyorsanız, davranış biraz farklıdır. Kodum etkinken, hata ayıklayıcı Kodumun dışına atılan ve Kodumdan geçmeyen birinci şans ortak dil çalışma zamanı (CLR) istisnalarını yok sayar.


59

Simon Mourier bu örneği verdi :

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

burada bir kutudan çıkarma dönüşüm (döküm) den object (veya sınıflarının birinden System.ValueTypeveya System.Enumveya bir arayüz türünden) için (başka bir değer türü Nullable<>kendi içinde) elde edilir NullReferenceException.

Diğer yönde, bir boks dönüşüm gelen bir Nullable<>yer alır HasValueeşit false için bir referans tipi, verebilir nulldaha sonra bir yol açabilir referans NullReferenceException. Klasik örnek şöyledir:

DateTime? d = null;
var s = d.ToString();  // OK, no exception (no boxing), returns ""
var t = d.GetType();   // Bang! d is boxed, NullReferenceException

Bazen boks başka bir şekilde olur. Örneğin, bu genel olmayan uzantı yöntemiyle:

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

aşağıdaki kod sorunlu olacaktır:

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

Bu durumlar, çalışma zamanının boks Nullable<>örnekleri için kullandığı özel kurallar nedeniyle ortaya çıkar .


42

Varlık çerçevesinde kullanılan varlık için sınıf adı, bir web formu kod arkası dosyası için sınıf adıyla aynı olduğunda durum ekleme.

Codebehind sınıfı Contact olan bir iletişim formunuz ve Contact adınız olan bir varlık formunuz olduğunu varsayalım.

Bağlamı çağırdığınızda, aşağıdaki kod bir NullReferenceException özel durumu atar.

Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line

Bütünlük uğruna DataContext sınıfı

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

ve Kişi varlık sınıfı. Bazen varlık sınıfları kısmi sınıflardır, böylece bunları başka dosyalarda da genişletebilirsiniz.

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

Hata hem varlık hem de codebehind sınıfı aynı ad alanında olduğunda oluşur. Bunu düzeltmek için, contact.aspx için varlık sınıfını veya codebehind sınıfını yeniden adlandırın.

Sebep hala neden olduğundan emin değilim. Ancak varlık sınıflarından herhangi biri System.Web.UI.Page öğesini genişlettiğinde bu hata oluşur.

Tartışma için DbContext.saveChanges () NullReferenceException bir göz atın


41

Bir kişinin bu istisnayı alabileceği bir diğer genel durum, birim testi sırasında alay sınıflarını içerir. Kullanılan alaycı çerçeveden bağımsız olarak, sınıf hiyerarşisinin tüm uygun düzeylerinin uygun şekilde alay edildiğinden emin olmalısınız. Özellikle, tüm özellikleri HttpContexttest edilen kod tarafından referans alınan alay edilmelidir.

Biraz ayrıntılı bir örnek için bkz. " Özel AuthorizationAttribute test edilirken atılan " NullReferenceException ".


40

Buna cevap vermek için farklı bir bakış açım var. Bu tür cevaplar "bundan kaçınmak için başka ne yapabilirim? "

Farklı katmanlar üzerinde çalışırken , örneğin bir MVC uygulamasında, bir denetleyicinin ticari işlemleri çağırmak için hizmetlere ihtiyacı vardır. Bu tür senaryolarda NullReferenceException özel durumundan kaçınmak için hizmetleri başlatmak üzere Bağımlılık Enjeksiyon Kapsayıcısı kullanılabilir . Bu, null olup olmadığını kontrol etme konusunda endişelenmeniz gerekmediği anlamına gelir ve hizmetleri her zaman tek birton veya bir prototip olarak kullanılabilir (ve başlatılmış) gibi denetleyiciden arayın.

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: Bu yalnızca başlatılmamış bağımlılıkların olduğu tek bir senaryoyu işler. Bu, NullReferenceException için bir azınlık senaryosudur. Çoğu durumda, nesnelerin nasıl çalıştığına dair basit bir yanlış anlama vardır. Bir sonraki en sık, geliştiricinin nesnenin otomatik olarak başlatılacağını varsaydığı diğer durumlardır.
John Saunders

Bağımlılık enjeksiyonu genellikle NullReferenceException durumundan kaçınmak için kullanılmaz. Burada genel bir senaryo bulduğuna inanmıyorum. Her durumda, cevabınızı stackoverflow.com/a/15232518/76337 tarzında olacak şekilde düzenlerseniz, o zaman aşağı oyu kaldıracağım.
John Saunders

38

" Bu konuda ne yapmalıyım" konusunda birçok cevap olabilir.

Bu tür hata koşullarını geliştirirken önlemenin daha "resmi" bir yolu, kodunuzda sözleşme ile tasarım uygulamaktır . Bu, geliştirirken sınıf değişmezlerini ve / veya hatta işlev / yöntem ön koşullarını ve son koşullarını ayarlamanız gerektiği anlamına gelir .

Kısacası, sınıf değişmezleri , normal kullanımda ihlal almazsınız Sınıfınızdaki bazı kısıtlamalar olacağı (ve dolayısıyla, sınıf olacak sağlamak değil tutarsız bir durumda olsun). Önkoşullar , bir işleve / yönteme girdi olarak verilen verilerin ayarlanan bazı kısıtlamalara uyması ve bunları asla ihlal etmemesi gerektiği anlamına gelir ve önkoşullar , bir işlev / yöntem çıktısının hiçbir zaman ihlal etmeden ayarlanan kısıtlamaları tekrar izlemesi gerektiği anlamına gelir. Sözleşme şartları gerektiğini asla bu nedenle olurken, hata ayıklama modunda pratikte kontrol edilir sözleşme tasarım, bir hata içermeyen bir program yürütülürken ihlal sürümlerde devre dışı gelişmiş sistem performansını maksimize etmek.

Bu şekilde, NullReferenceExceptionayarlanan kısıtlamaları ihlal eden durumlardan kaçınabilirsiniz . Örneğin, Xbir sınıfta bir nesne özelliği kullanır ve daha sonra yöntemlerinden birini çağırmayı denerseniz ve Xnull değeri varsa, bu aşağıdakilere yol açar NullReferenceException:

public X { get; set; }

public void InvokeX()
{
    X.DoSomething(); // if X value is null, you will get a NullReferenceException
}

Ancak, yöntem önkoşulu olarak "X özelliği hiçbir zaman boş değerli olmamalıdır" değerini ayarlarsanız, daha önce açıklanan senaryoyu önleyebilirsiniz:

//Using code contracts:
[ContractInvariantMethod]
protected void ObjectInvariant () 
{
    Contract.Invariant ( X != null );
    //...
}

Bu nedenle, .NET uygulamaları için Kod Sözleşmeleri projesi bulunmaktadır.

Alternatif olarak, sözleşme ile tasarım iddialar kullanılarak uygulanabilir .

GÜNCELLEME: Terimin, Eyfel programlama dili tasarımı ile bağlantılı olarak Bertrand Meyer tarafından oluşturulduğunu belirtmek gerekir .


2
Bunu hiç kimse bundan bahsetmediği gibi eklemeyi düşündüm ve bir yaklaşım olarak var olduğu ölçüde, amacım konuyu zenginleştirmekti.
Nick Louloudakis

2
Konuyu zenginleştirdiğiniz için teşekkür ederiz. Eklemeyle ilgili fikrimi verdim. Şimdi başkaları da aynısını yapabilir.
John Saunders

2
Bu son derece görüntülenen bir iş parçacığı verilen bu konuya değerli bir ek olduğunu düşündüm. Daha önce kod sözleşmeleri duydum ve bu onları kullanmayı düşünmek için iyi bir hatırlatma oldu.
VoteCoffee

36

NullReferenceExceptionBoş bir nesnenin Özelliklerine erişmeye çalıştığımızda veya bir dize değeri boş olduğunda ve dize yöntemlerine erişmeye çalıştığımızda A atılır.

Örneğin:

  1. Boş bir dizenin dize yöntemine erişildiğinde:

    string str = string.Empty;
    str.ToLower(); // throw null reference exception
  2. Boş bir nesnenin özelliğine erişildiğinde:

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

2
Bu yanlış. String.Empty.ToLower()boş bir başvuru istisnası atmaz. Boş da olsa gerçek bir dizeyi temsil eder (yani ""). Bunun çağrılacak bir nesnesi olduğundan ToLower(), orada boş bir referans istisnası atmak mantıklı olmaz.
Kjartan

31

TL; DR: kullanmayı deneyin Html.PartialyerineRenderpage


Object reference not set to an instance of an objectBir Görünüm içinde bir Görünüm göndermeye çalıştığımda, şöyle bir Model göndererek alıyordum :

@{
    MyEntity M = new MyEntity();
}
@RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null

Hata ayıklama, modelin MyOtherView içinde Null olduğunu gösterdi. Şunu değiştirene kadar:

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

Ve işe yaradı.

Ayrıca, Html.Partialbaşlamak zorunda kalmamamın nedeni, Visual Studio'nun farklı bir şekilde oluşturulmuş bir döngü içinde olması durumunda bazen hata görünümlü dalgalı çizgiler atmasıydı , çünkü gerçekten bir hata olmasa da:Html.Partialforeach

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

Ama uygulamayı bu "hata" ile sorunsuz çalıştırabildim. foreachDöngünün yapısını aşağıdaki gibi değiştirerek hatadan kurtulabildim :

@foreach(var M in MyEntities){
    ...
}

Bir hissim olmasına rağmen, Visual Studio ve işaretleri ve parantezleri yanlış okuduğu için.


Siz istediniz Html.Partial, değil@Html.Partial
John Saunders

Ayrıca, lütfen hangi satırın istisnayı attığını ve nedenini gösterin.
John Saunders

Hata, burada dahil etmediğim MyOtherView.cshtml'de meydana geldi, çünkü Model düzgün bir şekilde gönderilmiyordu (öyleydi Null), bu yüzden hatanın Modeli nasıl gönderdiğimle ilgili olduğunu biliyordum.
Travis Heeter

22

Bu konuda ne yapabilirsiniz?

Burada null referansın ne olduğunu ve nasıl hata ayıklanacağını açıklayan birçok iyi cevap var. Ancak sorunu nasıl önleyeceğiniz veya en azından yakalamayı nasıl kolaylaştıracağınız hakkında çok az şey var.

Bağımsız değişkenleri kontrol edin

Örneğin, yöntemler null olup olmadıklarını görmek için farklı argümanları kontrol edebilir ve ArgumentNullExceptionbu kesin amaç için açık bir şekilde oluşturulmuş bir istisna a.

Even için yapıcı ArgumentNullException, parametrenin adını ve bir mesajı argüman olarak alır, böylece geliştiriciye sorunun tam olarak ne olduğunu söyleyebilirsiniz.

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

Araçları Kullan

Ayrıca yardımcı olabilecek birkaç kütüphane vardır. Örneğin "Resharper" kodu yazarken, özellikle de özniteliklerini kullanıyorsanız uyarı verebilir : NotNullAttribute

Çalışma Contract.Requires(obj != null)zamanı ve derleme denetimi sağlayan sözdizimini kullandığınız "Microsoft Kod Sözleşmeleri" vardır : Kod Sözleşmelerini Tanıtma .

Ayrıca, sadece bunun gibi özellikleri kullanmanıza izin verecek "PostSharp" var:

public void DoSometing([NotNull] obj)

Bunu yaparak ve PostSharp'ı oluşturma işleminizin bir parçası haline getirerek objçalışma zamanında null olup olmadığını kontrol edin. Bkz. PostSharp null denetimi

Açık Kod Çözümü

Veya her zaman düz eski kodu kullanarak kendi yaklaşımınızı kodlayabilirsiniz. Örneğin, boş referansları yakalamak için kullanabileceğiniz bir yapı. Aynı konseptten sonra modellenmiştir Nullable<T>:

[System.Diagnostics.DebuggerNonUserCode]
public struct NotNull<T> where T: class
{
    private T _value;

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

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

            _value = value;
        }
    }

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

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

Nullable<T>İzin vermemek için tam tersini başarma amacı dışında, kullandığınız gibi çok benzer şekilde kullanırsınız null. İşte bazı örnekler:

NotNull<Person> person = null; // throws exception
NotNull<Person> person = new Person(); // OK
NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null

NotNull<T>dolaylı olarak yayınlanır ve Tböylece ihtiyacınız olan her yerde kullanabilirsiniz. Örneğin, bir Personnesneyi aşağıdakileri alan bir yönteme iletebilirsiniz NotNull<Person>:

Person person = new Person { Name = "John" };
WriteName(person);

public static void WriteName(NotNull<Person> person)
{
    Console.WriteLine(person.Value.Name);
}

Yukarıda nullable ile olduğu gibi görebileceğiniz gibi, Valueözellik üzerinden temel değere erişirsiniz . Alternatif olarak, açık veya kapalı bir kadro kullanabilirsiniz, aşağıdaki dönüş değeri olan bir örnek görebilirsiniz:

Person person = GetPerson();

public static NotNull<Person> GetPerson()
{
    return new Person { Name = "John" };
}

Ya da yöntem sadece T(bu durumda Person) bir döküm yaparak geri döndüğünde kullanabilirsiniz . Örneğin, aşağıdaki kod aynen yukarıdaki kodu ister:

Person person = (NotNull<Person>)GetPerson();

public static Person GetPerson()
{
    return new Person { Name = "John" };
}

Uzantı ile Birleştir

NotNull<T>Bir uzantı yöntemiyle birleştirin ve daha da fazla durumu kapsayabilirsiniz. Uzantı yönteminin nasıl görünebileceğine ilişkin bir örnek:

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

Ve işte nasıl kullanılabileceğine bir örnek:

var person = GetPerson().NotNull();

GitHub

Referansınız için yukarıdaki kodu GitHub'da kullanılabilir hale getirdim, bulabilirsiniz:

https://github.com/luisperezphd/NotNull

İlgili Dil Özelliği

C # 6.0 bu konuda biraz yardımcı olan "null koşullu işleç" i tanıttı. Bu özellik sayesinde, iç içe geçmiş nesnelere başvurabilirsiniz ve bunlardan herhangi biri varsa nullifadenin tamamı geri döner null.

Bu, bazı durumlarda yapmanız gereken boş kontrol sayısını azaltır. Sözdizimi, her noktadan önce bir soru işareti koymaktır. Örneğin, aşağıdaki kodu ele alalım:

var address = country?.State?.County?.City;

Bunun country, Countryadı verilen bir özelliğe sahip türden bir nesne olduğunu düşünün State. Eğer country, State, Countyveya Cityolduğu nulldaha sonra address will beboş . Therefore you only have to check whetheradres isnull`.

Harika bir özellik, ancak size daha az bilgi veriyor. 4'ten hangisinin boş olduğu belli değil.

Nullable gibi yerleşik?

C # için güzel bir stenografi vardır Nullable<T>, böyle bir türden sonra bir soru işareti koyarak nullable bir şey yapabilirsiniz int?.

C # gibi bir şey olsaydı iyi olurdu NotNull<T>yukarıda yapı ve belki de benzer işarkadaşı ünlem işareti vardı gibi bir şey yazabilirsiniz ki (!): public void WriteName(Person! person).


2
NullReferenceException'ı asla atmayın
John Saunders

@JohnSaunders neden sormaya cesaret edebilirim? (Cidden neden olsa?)
Luis Perez

2
NullReferenceException, CLR tarafından atılmalıdır. Bu, bir null değerine başvuru yapıldığı anlamına gelir. İlk önce akıllıca kontrol etmeniz dışında bir null değerine başvurunun gerçekleşeceği anlamına gelmez.
John Saunders

Bunun nasıl kafa karıştırıcı olabileceği konusundaki görüşünüzü görüyorum. Bu örnek için düzenli bir istisna ve GitHub'da özel bir istisna güncelledim.
Luis Perez

Böyle basit bir soru için harika bir cevap. Başarısız olan kodunuz olduğunda o kadar da kötü değil. Güvendiğiniz bazı ticari bir üçüncü taraf kütüphanesinin derinliklerinden geldiğinde korkunç ve müşteri desteği, soruna neden olan kodunuz olması gerektiğinde ısrar ediyor. Ve tamamen emin değilsiniz ve tüm proje durmak için zemin olduğunu .. Aslında bu benim mezar taşı için uygun bir söz olabilir düşünüyorum: "Nesne başvurusu bir nesnenin örneğine ayarlanmadı."
Darrel Lee

10

İlginçtir, bu sayfadaki cevapların hiçbiri iki uç durumdan bahsetmiyor, bunları eklersem kimsenin aklına gelmez:

Edge durumu # 1: Sözlüğe eşzamanlı erişim

.NET'teki genel sözlükler iş parçacığı için güvenli değildir ve iki eşzamanlı iş parçacığından bir anahtara erişmeye çalıştığınızda bazen bir NullReferenceveya daha sık (daha sık) a atabilirler KeyNotFoundException. Bu durumda istisna oldukça yanıltıcıdır.

Kenar durumu 2: güvenli olmayan kod

A kodla NullReferenceExceptionatılırsa unsafe, işaretçi değişkenlerinize bakabilir ve bunları kontrol edebilirsiniz IntPtr.Zero. Aynı şey ("boş işaretçi istisnası"), ancak güvenli olmayan kodda, değişkenler genellikle değer türleri / diziler vb. İçin kullanılır ve bir değer türünün bunu nasıl atabileceğini merak ederek başınızı duvara vurursunuz istisna.

(Bu arada, güvenli olmadıkça güvenli olmayan kod kullanmamanın başka bir nedeni)


5
Sözlük örneğiniz bir uç durum değil. Nesne iş parçacığı için güvenli değilse, birden çok iş parçacığından kullanmak rasgele sonuçlar üretir. Güvenli olmayan kod örneğiniz nullhangi yoldan farklı ?
John Saunders

10

C # 6'da Null koşullu işleçleri kullanarak NullReferenceException'ı temiz bir şekilde düzeltebilir ve null denetimleri işlemek için daha az kod yazabilirsiniz.

Üye erişimi (?.) Veya dizin (? [) İşlemini gerçekleştirmeden önce null değerini sınamak için kullanılır.

Misal

  var name = p?.Spouse?.FirstName;

şuna eşittir:

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

Sonuç olarak, p boşken veya p boşken ad boş olacaktır.

Aksi takdirde, değişken adına p.Spouse.FirstName değeri atanır.

Daha fazla bilgi için: Koşulsuz Operatörler


9

"Nesne başvurusu bir nesnenin örneğine ayarlanmadı" hata satırı, nesne nesnesine örnek nesne atamadığınızı ve yine de o nesnenin properies / yöntemlerine eriştiğinizi belirtir.

örneğin: myClass adında bir sınıfınız olduğunu ve bir tane prop1 özelliği içerdiğini varsayalım.

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

Şimdi bu prop1'e aşağıdaki gibi başka bir sınıfta erişiyorsunuz:

public class Demo
{
     public void testMethod()
     {
        myClass ref = null;
        ref.prop1 = 1;  //This line throws error
     }
}

sınıfın myClass sınıfının başvurusu bildirilmiş ancak somutlaştırılmamış veya nesnenin bir örneği söz konusu sınıfın başvuru örneğine atanmamış olduğu için yukarıdaki satır hata veriyor.

Bunu düzeltmek için başlatmanız gerekir (bu sınıfın referansına nesne atayın).

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

4

Kullanmaya çalıştığınız sınıfın bir nesnesi örneklenmediğinde, bir nesnenin örneğine ayarlanmayan NullReferenceException veya Object başvurusu oluşur. Örneğin:

Öğrenci adında bir sınıfınız olduğunu varsayın.

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

Şimdi, öğrencinin tam adını almaya çalıştığınız başka bir sınıfı düşünün.

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

Yukarıdaki kodda görüldüğü gibi, Öğrenci s - ifadesi yalnızca Öğrenci türünün değişkenini bildirir, bu noktada Öğrenci sınıfının somutlaştırılmadığını unutmayın. Bu nedenle, s.GetFullName () ifadesi çalıştırıldığında, NullReferenceException özel durumunu atar.


3

Basit bir ifadeyle:

Oluşturulmamış veya şu anda bellekte olmayan bir nesneye erişmeye çalışıyorsunuz.

Peki bununla nasıl başa çıkılır:

  1. Hata ayıklama ve hata ayıklayıcı kırmak ... Doğrudan sizi kırık değişkene götürecek ... Şimdi senin görevin bunu düzeltmek için .. Yeni anahtar kelimeyi uygun yerde kullanarak.

  2. Nesne olmadığı için bazı veritabanı komutlarında kaynaklanıyorsa, tek yapmanız gereken boş bir denetim yapmak ve bunu işlemektir:

    if (i == null) {
        // Handle this
    }
  3. En zor olanı ... GC nesneyi zaten topladıysa ... Bu genellikle dizeleri kullanarak bir nesne bulmaya çalışıyorsanız gerçekleşir ... Yani, nesnenin adına göre bulmak, GC'nin zaten temizledim ... Bu bulmak zor ve oldukça sorun olacak ... Bu sorunu çözmenin daha iyi bir yolu, geliştirme sürecinde gerekli olan her yerde null kontroller yapmaktır. Bu size çok zaman kazandıracak.

İsimle bularak, bazı çerçeve dizeleri kullanarak FIndObjects izin sağlar ve kod şöyle görünebilir: FindObject ("ObjectName");


3
Bir nesneye referansınız varsa, GC onu asla temizlemez
John Saunders

2
Eğer FindObject ( "Nesne Adı") gibi şeyler kullanıyorsanız hiçbir şekilde GC sen refernece nesne edeceklerini elden önce bilecek yoktur .. bu bu çalışma zamanında meydana .. explaing çalışıyordu budur
Akash Gutha

2
City'de Unity gibi bu işlevselliği sağlayan bazı çerçeveler vardır. sorunun BCl ile ilgili hiçbir şeyi yoktur. Eleştirmeden önce internette arama yapın Onlar gibi bir sürü fonksiyon var ve ur tür bilgileri için günlük bile kullanıyorum. Şimdi lütfen cevabın nasıl bir mantık yaratmadığını söyle.
Akash Gutha

2
docs.unity3d.com/ScriptReference/… bağlantıyı kontrol edin ve kendinizi düzeltin mr.expert: p
Akash Gutha

Bağlantınızda gördüğüm örnekler GameObject.Find sonuçlarını bir üye alanına atar. Bu bir referanstır ve GC, içerdiği nesne toplanana kadar onu toplamaz.
John Saunders

1

Kelimenin tam anlamıyla bir NullReferenceExeption düzeltmek için en kolay yolu iki yolu vardır. Örneğin bir betiği ve rb (rigidbody) adında bir değişkeni olan bir GameObject öğeniz varsa, bu değişken oyununuzu başlattığınızda null başlar.
Bu nedenle, bilgisayarda bu değişkente depolanmış veriler olmadığından bir NullReferenceExeption elde edersiniz.

Örnek olarak bir RigidBody değişkeni kullanacağım.
Verileri gerçekten kolayca birkaç şekilde ekleyebiliriz:

  1. AddComponent> Fizik> Rigidbody ile nesnenize bir RigidBody ekleyin
    Daha sonra betiğinize girin ve yazın rb = GetComponent<Rigidbody>();
    Bu kod satırı sizin Start()veya Awake()fonksiyonlarınız altında en iyi şekilde çalışır .
  2. Bir bileşeni programlı olarak ekleyebilir ve değişkeni aynı anda bir kod satırı ile atayabilirsiniz: rb = AddComponent<RigidBody>();

Diğer Notlar: Birliğin nesnenize bir bileşen eklemesini istiyorsanız ve bir bileşen eklemeyi unutmuş olabilirseniz [RequireComponent(typeof(RigidBody))], sınıf bildiriminizin üzerine yazabilirsiniz (tüm kullanıcılarınızın altındaki boşluk).
Zevk ve eğlenceli oyunlar yapmak!


-1

Bu kural dışı durumun atılabileceği yaygın senaryoları göz önünde bulundurursak, üstteki nesneye sahip özelliklere erişiriz.

Ör:

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

burada, adres null ise, NullReferenceException elde edersiniz.

Bu nedenle, bir uygulama olarak, bu tür nesnelerde (özellikle genel olarak) özelliklere erişmeden önce her zaman null check kullanmalıyız

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

-3

Bu temelde bir Null referans istisnasıdır . As Microsoft devletlerde

Değeri null olan türdeki bir üyeye erişmeye çalıştığınızda bir NullReferenceException özel durumu atılır.

Bu ne anlama geliyor?

Bu, herhangi bir değeri olmayan herhangi bir üye varsa ve bu üyeyi belirli bir görevi yerine getirmesi için yaparsak, sistem şüphesiz bir mesaj atar ve

"Hey bekle, o üyenin değeri yok, bu yüzden teslim ettiğin görevi yerine getiremiyor."

İstisna, bir şeyin yönlendirildiğini ancak değerinin ayarlanmadığını söylüyor. Dolayısıyla, bu değer yalnızca referans türleri kullanılırken oluştuğuna işaret eder, çünkü Değer türleri geçersizdir.

Değer türü üyeler kullanırsak, NullReferenceException oluşmaz.

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

Yukarıdaki kod, boş bir değerle atanan basit dizeyi gösterir .

Şimdi, dize uzunluğunu yazdırmaya çalıştığımda str , ben alırım 'System.NullReferenceException' tür bir işlenmeyen istisna oluştu üyesi çünkü mesajı str boş işaret ettiği ve null herhangi bir uzunlukta olamaz.

' NullReferenceException ', başvuru türünü başlatmayı unuttuğumuzda da oluşur.

İçinde bir sınıf ve üye yöntemi olduğunu varsayalım. Sınıfımı başlattım, sadece sınıfımı adlandırdım. Şimdi yöntemi kullanmaya çalışırsam, derleyici bir hata atar veya bir uyarı verir (derleyiciye bağlı olarak).

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

    }
}

Yukarıdaki kodun derleyicisi, değişken nesnesinin boş değerlere sahip olduğunu ya da hiçbir şeyin boşta olmadığını belirten obj nesnesinin atanmamış olduğuna dair bir hata oluşturur . Yukarıdaki kodun derleyicisi, değişken nesnesinin boş değerlere sahip olduğunu ya da hiçbir şeyin boşta olmadığını belirten obj nesnesinin atanmamış olduğuna dair bir hata oluşturur .

Neden oluşur?

  • NullReferenceException, nesnenin değerini denetlemememiz nedeniyle ortaya çıkıyor. Kod geliştirmede genellikle nesne değerlerini işaretlemeden bırakırız.

  • Nesnelerimizi somutlaştırmayı unuttuğumuzda da ortaya çıkar. Boş değerleri döndürebilen veya ayarlayabilen yöntemler, özellikler, koleksiyonlar vb. Kullanmak da bu istisnanın nedeni olabilir.

Nasıl önlenebilir?

Bu ünlü istisnayı önlemek için çeşitli yollar ve yöntemler vardır:

  1. Açık Kontrol: Nesneleri, özellikleri, yöntemleri, dizileri ve koleksiyonları boş olup olmadıklarını kontrol etme geleneğine uymalıyız. Bu, if-else if-else vb. Gibi koşullu ifadeler kullanılarak basitçe uygulanabilir.

  2. İstisna yönetimi: Bu istisnayı yönetmenin önemli yollarından biri. Basit try-catch-nihayet blokları kullanarak bu istisnayı kontrol edebilir ve bir günlüğünü tutabiliriz. Bu, uygulamanız üretim aşamasındayken çok yararlı olabilir.

  3. Null işleçler: Null Coalescing operatörü ve null koşullu işleçler, nesnelere, değişkenlere, özelliklere ve alanlara değerler ayarlanırken de kullanışlı olarak kullanılabilir.

  4. Hata ayıklayıcı: Geliştiriciler için büyük hata ayıklama silahımız var. Geliştirme yüzü sırasında NullReferenceException ile karşılaşırsak, istisnanın kaynağına ulaşmak için hata ayıklayıcıyı kullanabiliriz.

  5. Yerleşik yöntem: GetValueOrDefault (), IsNullOrWhiteSpace () ve IsNullorEmpty () gibi sistem yöntemleri null olup olmadığını denetler ve null değeri varsa varsayılan değeri atar.

Burada zaten çok iyi cevaplar var. Blogumdaki örneklerle daha ayrıntılı açıklamayı da kontrol edebilirsiniz .

Umarım bu da yardımcı olur!


Temel olarak bu blog gönderisinin yarısını kopyaladınız ve mevcut yanıtların ele almadığı yeni bir şey eklemediniz.
CodeCaster

@codecaster Kendi blogunuzdan bir özeti yeniden yazdığınızda kopyalamanın söylendiği söyleniyor. Cevabımda yeni bir şey olmadığını ve önceki cevapların sahip olmadığı yeni bir şey olmadığını biliyorum, ancak daha sofistike bir şekilde katkıda bulunmak ve başkalarının anladığım yolu anlamasına izin vermek istiyorum. Tek bir kişiye yardım etse bile sevinecektir. İyi niyetle.
Wasim

-4

Derleme kaydedilirken veya derlenirken bu ileti görüntüleniyorsa, tüm dosyaları kapatın ve derlemek ve kaydetmek için herhangi bir dosyayı açın.

Benim için sebebi dosyayı yeniden adlandırmıştım ve eski dosya hala açıktı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.