Nullable <int> değerini artırmak neden bir özel durum oluşturmaz?


98

Açıklar mısınız, Console.WriteLine neden boş bir satır yazıyor ( Console.WriteLine(null)bana derleme hatası veriyor) ve neden NullReferenceException olmadığını (hatta a+=1yükseltmemesi gerektiğini) açıklar mısınız?

int? a = null;
a++; // Why there is not NullReferenceException? 
Console.WriteLine(a); // Empty line

Her üç operatöründen ++, +=ve +varyantları kaldırdık. Bu nedenle ifadeleri a++;, a += 1;ve a = a + 1;tüm izin verilir. Başlangıçta nullise her ürün (istisnasız) . anull
Jeppe Stig Nielsen

5
NullReferenceException? ama int?bir değil Reference, bu sadece değer intalabilen bir şeynull
Khaled. K

Yanıtlar:


124

Kaldırılmış bir operatörün etkilerini gözlemliyorsunuz .

C # 5 spesifikasyonunun 7.3.7 bölümünden:

Kaldırılan işleçler, null yapılamayan değer türlerinde çalışan önceden tanımlanmış ve kullanıcı tanımlı işleçlerin bu türlerin null atanabilir biçimleriyle de kullanılmasına izin verir. Kaldırılan operatörler, aşağıda açıklandığı gibi belirli gereksinimleri karşılayan önceden tanımlanmış ve kullanıcı tanımlı operatörlerden oluşturulmuştur:

  • Tek terimli işleçler + ++ - -- ! ~ için, işlenen ve sonuç türlerinin her ikisi de null yapılamayan değer türleriyse, bir işlecin yükseltilmiş formu vardır. Yükseltilmiş form, ?işlenen ve sonuç türlerine tek bir değiştirici eklenerek oluşturulur . Kaldırılan operatör, işlenen null ise boş bir değer üretir. Aksi takdirde, kaldırılan operatör işleneni açar, temeldeki operatörü uygular ve sonucu sarar.

Yani temelde, a++bu durumda null(olarak int?) sonucu olan bir ifadedir ve değişkene dokunulmadan bırakılır.

Aradığın zaman

Console.WriteLine(a);

kutu içine alınır object, bu da onu boş bir satır olarak yazdırılan boş bir referansa dönüştürür.


3
Kullanmadan "boş" yazdırmanın bir yolu var mı Console.WriteLine(a == null ? "null" : a)?
Cole Johnson

5
@Cole Johnson: Console.WriteLine (a ?? "boş"); :)
David Chappelle

2
@DavidChappelle When atüründe int?, a ?? "null"iki işlenen için ortak bir tür bulmadığını söyleyebilirim . objectYaygın tipte bir ipucuna ihtiyacınız var . Öyleyse işlenenlerden birini buna dökün. aKutulu edilecektir. Örneğin ((object)a) ?? "null"veya a ?? (object)"null".
Jeppe Stig Nielsen

Süper. şartnameye bağlayabilir misin? bunu kendi sınıflarımızdaki operatörleri aşırı yüklediğimizde tanımlayabilir miyiz?
Phil

@teabaggs: Şu anda kolayca bağlantı kuramıyorum ve bağlantı yalnızca bir Word belgesine (bir arama ile kolayca bulabileceğiniz) olabilir. Uygun olduğunda, operatör aşırı yüklerini tanımladığınızda otomatik olarak kaldırılan operatörler alırsınız.
Jon Skeet

116

Jon'un cevabı doğru ama bazı ek notlar ekleyeceğim.

Neden Console.WriteLine(null)derleme hatası veriyor?

19 tane aşırı yükleme vardır Console.WriteLineve bunlardan üçü a'ya uygulanabilir null: a'yı alan string, a'yı alan char[]ve bir alan an object. C # bu üçünden hangisini kastettiğinizi belirleyemez, bu nedenle bir hata verir. Console.WriteLine((object)null)yasal olurdu çünkü şimdi açık.

neden Console.WriteLine(a)boş bir satır yazıyor?

a boş int? . Aşırı yük çözünürlüğü object, yöntemin sürümünü seçer , bu nedenle, int?boş bir referans olarak kutulanır. Yani bu, temelde Console.WriteLine((object)null)boş bir satır yazan ile aynıdır .

Artışta neden yok NullReferenceException?

Endişelendiğiniz boş referans nerede ? abaşlangıç ​​için bir int?başvuru türü olmayan bir boş değerdir ! Unutmayın, boş değer atanabilir değer türleri değer türleridir , başvuru türleri değildir ; bu nedenle, bir başvuru türüne göre kutulanmadıkça başvuru anlamlarına sahip olmalarını beklemeyin. İlavede boks yok.


0

Null artırıyor musunuz ???

int? a = null;
a++;

Bu ifade basitçe null++yani null + 1 anlamına gelir .

Bu belgeye göre, null yapılabilir bir tür, temel alınan değer türü için doğru değer aralığını ve ek bir boş değeri temsil edebilir. "Nullable of Int32" olarak telaffuz edilen Nullable, -2147483648 ila 2147483647 arasında herhangi bir değer atanabilir veya boş değer atanabilir

Burada null değerini artırıyorsunuz, o zaman da 0 değil null değer veya başka bir tamsayı olacaktır.

Neden hata yerine boş yazdırıyor?

null değeri olan null yapılabilir bir tür yazdırdığınızda, bir değişken ie değerini bir bellek konumu yazdırdığınız için hata yerine boş yazdırır. bu, boş veya herhangi bir tam sayı olabilir.

Ancak null kullanarak null yazdırmaya çalıştığınızda Console.WriteLine(null), null bir değişken olmadığından herhangi bir bellek konumuna başvurmaz. Ve dolayısıyla hata verir "NullReferenceException".

O halde herhangi bir tamsayıyı Console.WriteLine(2);?? kullanarak nasıl yazdırabilirsiniz ?

Bu durumda, 2 geçici konumda hafızaya girecek ve işaretçi yazdırmak için bu hafıza konumuna işaret edecektir.

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.