C # nullable int nasıl int dönüştürülür


484

Nasıl null dönüştürebilirim intbir etmek int? Aşağıdaki gibi 2 tür int var:

int? v1;  
int v2; 

Ben atamak istediğiniz v1kadar 'nin değerini v2. v2 = v1;hataya neden olur. Nasıl dönüştürebilirim v1için v2?


İstenilen davranış nedir v1olduğu null?
Solomon Ucko

Yanıtlar:


637

Şimdiye kadar olan diğer cevapların hepsi doğrudur; Sadece biraz daha temiz olan bir tane daha eklemek istedim:

v2 = v1 ?? default(int);

Herhangi Nullable<T>biri dolaylı olarak onun dönüştürülebilir T, değerlendirilen tüm ifade hiçbir zaman bir ValueType için boş bir atama ile sonuçlanamaz. Yani, boş birleştirici operatör ??üçlü operatör için sadece sözdizimi şekeri:

v2 = v1 == null ? default(int) : v1;

... bir if / else için sözdizimi şekeri olan:

if(v1==null)
   v2 = default(int);
else
   v2 = v1;

Ayrıca, .NET 4.0'dan itibaren, Nullable<T>temel olarak yukarıda gösterilen null birleştirme işlemini gerçekleştiren bir null-güvenli alıcı olan "GetValueOrDefault ()" yöntemine sahiptir, bu yüzden bu da işe yarar:

v2 = v1.GetValueOrDefault();

4
default(int)gerçekten gerekli? Bir basit ile ilgili sorun nedir 0?
Cole Johnson

4
Bu örnek için işe yarayacaktır, ancak genel durumda defaultuygun olan yerlerde kullanılması önerilir . Sıfır her zaman bir değer olarak geçerli değildir, çok daha az varsayılan değerdir, bu nedenle intbir jenerik ile değiştirirseniz , Tkodum sıfır olmadan çalışmaz. Gelecekteki bazı çerçeve versiyonlarında, defaultyüklenebilir de olabilir; bu gerçekleşirse ve olduğunda, varsayılan kullanım kodundan kolayca faydalanılırken açık null veya sıfır atamaların değiştirilmesi gerekir.
KeithS

5
Bu en üste çıkmalıdır: .NET 4.0, Nullable <T> bir "GetValueOrDefault ()" var
RandomHandle

GetValueOrDefault ile düzenlemek için geri geldiğiniz için teşekkür ederiz!
CindyH

Varsayılanı kullandığınızda DateTime'a dikkat etmek isteyebilirsiniz. Bu, boş yerine varsayılan tarihi ekleyebilir.
Ranch Camal


92

Atama için Value özelliğini kullanabilirsiniz.

v2 = v1.Value;

8
Ayrıca - v1'de null olup olmadığından emin değilseniz, bir geri dönüş değeri ayarlamak için null birleştirme operatörünü kullanabilirsiniz. Örneğin v2 = v1 ?? 0;
Arjen

12
Ve önce kontrol ettiğinizden emin olun v1.HasValue.
Yuck

3
MSDN eğer bu bir istisna durumu olduğunu söylüyor v1olduğunu null. Bence bu doğru bir cevap değil.
ventiseis

6
@ventiseis Bunun arzu edilen davranış olduğunu düşünürdüm - diğer cevapların çoğunun sessiz bir şekilde null değerini 0'a dönüştürmeyle şaşırdım. Sıfırlanabilir bir türü nullable olmayan bir türe atarsanız, değer aslında boş değil. OP "v1'i v2'ye atamak istiyorum veya v1 boşsa 0'ı atamak istiyorum" demedi, ancak herkesin varsaydığı şey buydu
Michael Mrozek


49

Bunun v1bir değeri olduğunu biliyorsanız , Valueözelliği kullanabilirsiniz :

v2 = v1.Value;

GetValueOrDefaultYöntemin kullanılması, varsa bir değer atayacaktır, aksi takdirde tür için varsayılan veya belirttiğiniz varsayılan bir değer atanacaktır:

v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

Değeri HasValueolup olmadığını kontrol etmek için özelliği kullanabilirsiniz v1:

if (v1.HasValue) {
  v2 = v1.Value;
}

GetValueOrDefault(T)Yöntem için dil desteği de vardır :

v2 = v1 ?? -1;

Önce bir değer olup olmadığını kontrol etmeden değeri kullanmamalısınız. Kullan ?? operatör yerine.
Peter

45

V1 boşsa yapamazsınız, ancak bir operatörle kontrol edebilirsiniz.

v2 = v1 ?? 0;

28

GetValueOrDefault()

nesnenin değerini alır. Boşsa, int olan varsayılan değeri olan 0 değerini döndürür.

Misal:

v2= v1.GetValueOrDefault();


21

Belirli bir tür için varsayılan değer kabul edilebilir bir sonuçsa:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

Sonuç tanımsız olduğunda farklı bir varsayılan değer istiyorsanız:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

Yalnızca değerin döndürülmesini istiyorsanız (yöntem başarısız olsa da olmasa da):

v2 = v1.GetValueOrDefault();


.NET 4.7.2 .: GetValueOrDefault()herhangi bir denetim yapmadan alan değerini döndürür.


15

Ben endişeliyim kadarıyla en iyi çözüm GetValueOrDefault()yöntemi kullanmaktır .

v2 = v1.GetValueOrDefault();

Bu benim için en yararlı oldu
Liakat


10

ile mümkün v2 = Convert.ToInt32(v1);


Bu teknik olarak çalışır, ancak HasValue / Value veya GetValueOrDefault gibi diğer teknikler çok daha verimli çalışır.
Brandon Barkley


9

Arasında basit bir dönüştürme v1ve v2nedeniyle mümkün değildir v1daha değerlerin daha geniş bir alana sahiptir v2. Her şey v1artı nulldevlet tutabilir . Dönüştürmek intiçin, nulldurumu eşlemek için hangi değerin kullanılacağını açıkça belirtmeniz gerekir . Bunu yapmanın en basit yolu ??operatördür

v2 = v1 ?? 0;  // maps null of v1 to 0

Bu aynı zamanda uzun formda da yapılabilir

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}

9

Kullanım içeriğinize bağlı olarak, C # 7'nin desen eşleme özelliğini kullanabilirsiniz:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

DÜZENLE:

Bazı insanlar açıklama yapmadan aşağı oy kullandıklarından, bunu uygulanabilir bir çözüm olarak dahil etmenin mantığını açıklamak için bazı ayrıntılar eklemek istiyorum.

  • C # 7'nin desen eşleşmesi artık bir değerin türünü kontrol etmemizi ve bunu dolaylı olarak yayınlamamızı sağlıyor. Yukarıdaki snippet'te, if koşulu yalnızca içinde depolanan değer v1türüne uygun olduğunda v2(bu durumda) geçer int. Bunun sonucu, değeri v1olduğunda null, n- öğesinin null değerine atanamadığı için if-koşulunun başarısız olacağı sonucu çıkar int. Daha düzgün, nullbir değil int.

  • Bu çözümün her zaman en uygun seçenek olmadığını vurgulamak isterim. Önerdiğim gibi, bunun geliştiricinin tam kullanım bağlamına bağlı olacağına inanıyorum. Atanmış değer null değilse zaten bir int?ve varsa koşullu olarak değeri üzerinde çalışmak istiyorsanız (bu, boş bir int'i bilgi kaybetmeden normal bir int'e dönüştürmenin güvenli olduğu tek zamandır), örüntü eşleştirme belki de bunu yapmanın en kısa yollarından biridir.


Yeni bir değişken adı girme zorunluluğu talihsizdir, ancak varsayılan değer yoksa bu en iyi (en güvenli) çözümdür, çünkü HasValueçeklerinizi yanlışlıkla yeniden düzenleme riski yoktur .
minexew

Ben sadece v1.HasValue üzerinde kontrol ve sonra v1.Value üzerinde temel değere erişmek için bu yöntemin herhangi bir avantaj görmüyorum. Bunu küçümsemem, ancak bu sorunun zaten çözüldüğünü ve yeni bir tekniğin soruna fazla açıklık getirmediğini düşünüyorum. Ayrıca% 8-9 daha yavaş olarak değerlendirdim.
Brandon Barkley

Kıyasladığınız için teşekkürler, bunu bilmek güzel! Her iki şekilde de bakarsanız, fark en iyi ihtimalle marjinaldir (sanırım bunu bir süre kritik alanda yapmazsanız). Ben daha "özlü" veya muhtemelen "deyimsel" olarak bakıyorum çünkü API yerine dile pişmiş sözdizimi şekerler dayanmaktadır. Biraz öznel, ama belki de "daha sürdürülebilir". Gerçekten de, bu yaklaşımı diğer birçok cevabın önerdiği gibi varsayılan bir değere güvenmekten daha çok seviyorum.
Nicholas Miller

3

Değerini atayacaktır. v1 için v2bu boş değilse başka sıfır olarak varsayılan bir değer alacak.

v2=v1??0

Ya da aşağıda yazmanın diğer yolu.

v2 = v1.HasValue?v1:0


-1
 int v2= Int32.Parse(v1.ToString());

5
Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
xiawi

1
El yapımı hileler kullanmak yerine opsiyonelleri açmak için "en iyi uygulama" yolunu kullanmak daha iyidir. Referans için docs.microsoft.com/tr-tr/dotnet/csharp/language-reference/… adresine bakın
lorg

Sekiz yaşındaki bir soruyu on beş mevcut cevapla cevaplarken, cevabınızın hangi yeni yönünü ele aldığını açıklamak ve zamanın geçtiği yanıtı değiştirip değiştirmediğini not etmek önemlidir. Sadece kod cevapları neredeyse her zaman bazı açıklamalar eklenerek geliştirilebilir.
Jason Aller
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.