Bagaimana mengkonversi C # nullable int ke int

484

Bagaimana cara mengonversi nullable intmenjadi int? Misalkan saya memiliki 2 jenis int seperti di bawah ini:

int? v1;  
int v2; 

Saya ingin memberikan v1nilai kepada v2. v2 = v1;akan menyebabkan kesalahan. Bagaimana cara mengkonversi v1ke v2?

Kenthou
sumber
Apa perilaku yang diinginkan saat v1itu null?
Solomon Ucko

Jawaban:

637

Jawaban lain sejauh ini semuanya benar; Saya hanya ingin menambahkan satu lagi yang sedikit lebih bersih:

v2 = v1 ?? default(int);

Apa Nullable<T>pun secara implisit dapat dikonversi menjadi miliknya T, DISEDIAKAN bahwa seluruh ekspresi yang dievaluasi tidak pernah dapat menghasilkan penugasan nol ke ValueType. Jadi, operator null-coalescing ??hanyalah sintaksis gula untuk operator ternary:

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

... yang pada gilirannya adalah sintaksis gula untuk if / else:

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

Juga, pada .NET 4.0, Nullable<T>memiliki metode "GetValueOrDefault ()", yang merupakan pengambil aman-nol yang pada dasarnya melakukan penggabungan-nol yang ditunjukkan di atas, jadi ini juga berfungsi:

v2 = v1.GetValueOrDefault();
KeithS
sumber
4
Apakah default(int)benar-benar dibutuhkan? Apa yang salah dengan yang sederhana 0?
Cole Johnson
4
Ini akan berfungsi untuk contoh ini, tetapi dalam kasus umum disarankan untuk menggunakan yang defaultsesuai. Nol tidak selalu valid sebagai nilai, apalagi standarnya, jadi jika Anda mengganti intdengan generik TAnda akan menemukan kode saya berfungsi sementara nol tidak. Dalam beberapa versi kerangka kerja masa depan, defaultmungkin juga menjadi kelebihan beban; jika dan ketika itu terjadi, kode yang menggunakan standar akan dengan mudah dapat mengambil keuntungan, sementara penetapan nol atau nol yang eksplisit harus diubah.
KeithS
5
Ini akan naik ke atas: .NET 4.0, Nullable <T> memiliki "GetValueOrDefault ()"
RandomHandle
Terima kasih telah kembali mengeditnya dengan GetValueOrDefault!
CindyH
Anda mungkin ingin berhati-hati dengan DateTime ketika Anda menggunakan default. Ini mungkin memasukkan tanggal default bukan kosong.
Ranch Camal
168

Seperti ini,

if(v1.HasValue)
   v2=v1.Value
Srinivas Reddy Thatiparthy
sumber
92

Anda bisa menggunakan properti Value untuk penugasan.

v2 = v1.Value;
e36M3
sumber
8
Juga - jika Anda tidak yakin apakah v1 berisi nol - Anda dapat menggunakan operator penggabungan nol untuk menetapkan nilai cadangan. Misalnya v2 = v1 ?? 0;
Arjen
12
Dan pastikan untuk memeriksa v1.HasValuedulu.
Yuck
3
MSDN mengatakan, bahwa ini akan membuang pengecualian jika v1ada null. Menurut pendapat saya, ini bukan jawaban yang benar.
ventiseis
6
@ventiseis Saya akan berpikir itu adalah perilaku yang diinginkan - Saya terkejut begitu banyak jawaban lain baik-baik saja dengan diam-diam mengubah nol menjadi 0. Jika Anda menetapkan tipe nullable ke tipe non-nullable, Anda harus yakin bahwa nilai sebenarnya bukan nol. OP tidak mengatakan "Saya ingin menetapkan v1 ke v2, atau 0 jika v1 adalah nol", tetapi itulah yang tampaknya semua orang asumsikan
Michael Mrozek
82

Yang kamu butuhkan adalah..

v2= v1.GetValueOrDefault();
bintang
sumber
49

Jika Anda tahu yang v1memiliki nilai, Anda dapat menggunakan Valueproperti:

v2 = v1.Value;

Menggunakan GetValueOrDefaultmetode ini akan menetapkan nilai jika ada, jika tidak, default untuk tipe, atau nilai default yang Anda tentukan:

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

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

Anda dapat menggunakan HasValueproperti untuk memeriksa apakah v1memiliki nilai:

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

Ada juga dukungan bahasa untuk GetValueOrDefault(T)metode ini:

v2 = v1 ?? -1;
Guffa
sumber
Anda tidak harus menggunakan nilai tanpa terlebih dahulu memeriksa untuk melihat apakah ada nilai. Menggunakan ?? operator sebagai gantinya.
Peter
45

Anda tidak dapat melakukannya jika v1 nol, tetapi Anda dapat memeriksa dengan operator.

v2 = v1 ?? 0;
Arturo Martinez
sumber
28

GetValueOrDefault()

mengambil nilai objek. Jika nol, mengembalikan nilai default int, yaitu 0.

Contoh:

v2= v1.GetValueOrDefault();

Aniket Sharma
sumber
21

Jika nilai default untuk jenis yang diberikan adalah hasil yang dapat diterima:

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

Jika Anda menginginkan nilai default yang berbeda ketika hasilnya tidak ditentukan:

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

Jika Anda hanya ingin nilai dikembalikan (tidak masalah jika metode gagal atau tidak):

v2 = v1.GetValueOrDefault();


.NET 4.7.2 .: GetValueOrDefault()mengembalikan nilai bidang tanpa pengecekan.

GrzegorzF
sumber
15

Sejauh yang saya ketahui solusi terbaik adalah menggunakan GetValueOrDefault()metode.

v2 = v1.GetValueOrDefault();
Masoud Darvishian
sumber
yang ini paling berguna bagi saya
Liakat
11

Kon nullable ke int konversi dapat dilakukan seperti ini:

v2=(int)v1;
Krishna shidnekoppa
sumber
9
Jika v1 adalah nol, ini akan menyebabkan InvalidOperationException.
MungeWrath
10

itu mungkin dengan v2 = Convert.ToInt32(v1);

Putaran
sumber
Ini akan berfungsi secara teknis, tetapi teknik lain seperti HasValue / Value atau GetValueOrDefault berjalan jauh lebih efisien.
Brandon Barkley
9

Anda bisa melakukannya

v2 = v1.HasValue ? v1.Value : v2;
API Panda
sumber
9

Konversi sederhana antara v1dan v2tidak dimungkinkan karena v1memiliki domain nilai yang lebih besar daripada v2. Itu semua v1bisa tahan ditambah nullnegara. Untuk mengonversi, Anda harus secara eksplisit menyatakan nilai apa yang intakan digunakan untuk memetakan nullstatus. Cara paling sederhana untuk melakukan ini adalah ??operator

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

Ini juga bisa dilakukan dalam bentuk panjang

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

Bergantung pada konteks penggunaan Anda, Anda dapat menggunakan fitur pencocokan pola C # 7:

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

EDIT:

Karena beberapa orang downvoting tanpa meninggalkan penjelasan, saya ingin menambahkan beberapa detail untuk menjelaskan alasan untuk memasukkan ini sebagai solusi yang layak.

  • Pencocokan pola C # 7 sekarang memungkinkan kami memeriksa jenis nilai dan melemparkannya secara implisit. Dalam cuplikan di atas, jika-kondisi hanya akan berlalu ketika nilai yang disimpan di v1adalah tipe-kompatibel dengan tipe v2, yang dalam hal ini adalah int. Oleh karena itu ketika nilai untuk v1adalah null, jika-kondisi akan gagal karena nol tidak dapat ditugaskan ke int. Lebih tepatnya, nullbukan int.

  • Saya ingin menekankan bahwa solusi ini mungkin tidak selalu menjadi pilihan optimal. Seperti yang saya sarankan, saya percaya ini akan tergantung pada konteks penggunaan tepat pengembang. Jika Anda sudah memiliki int?dan ingin beroperasi secara kondisional pada nilainya jika-dan-hanya-jika nilai yang diberikan tidak nol (ini adalah satu-satunya waktu aman untuk mengkonversi int nullable ke int reguler tanpa kehilangan informasi), lalu pencocokan pola mungkin salah satu cara paling ringkas untuk melakukan ini.

Nicholas Miller
sumber
Perlunya memperkenalkan nama variabel baru sangat disayangkan, tetapi ini adalah solusi (teraman) terbaik jika tidak ada nilai default, karena tidak ada risiko secara tidak sengaja refactoring menjauh dari HasValuecek Anda .
minexew
Saya hanya tidak melihat keuntungan dari metode ini dibandingkan v1.HasValue sebagai cek dan kemudian v1.Value untuk mengakses nilai yang mendasarinya. Saya tidak akan menghapusnya, tapi saya pikir masalah ini sudah dipecahkan dan teknik baru tidak menambah banyak kejelasan untuk masalah ini. Saya juga menjadikannya 8-9% lebih lambat.
Brandon Barkley
Terima kasih telah membandingkannya, itu bagus untuk diketahui! Apa pun cara Anda melihatnya, perbedaannya adalah marjinal di terbaik (kecuali jika Anda melakukan ini di beberapa waktu kritis kurasa). Saya melihat ini menjadi lebih "ringkas" atau mungkin "idiomatik" karena ini bergantung pada gula sintaks yang dimasukkan ke dalam bahasa, bukan API. Agak subyektif, tapi mungkin "lebih bisa dipertahankan". Meskipun sungguh, saya lebih suka pendekatan ini daripada mengandalkan nilai default seperti yang disarankan oleh banyak jawaban lain.
Nicholas Miller
3

Ini akan memberikan nilai v1ke v2jika bukan nol, jika tidak maka akan mengambil nilai default sebagai nol.

v2=v1??0

Atau di bawah ini adalah cara lain untuk menulisnya.

v2 = v1.HasValue?v1:0
sagar
sumber
1

Di C # 7.1 dan yang lebih baru, ketik dapat disimpulkan dengan menggunakan defaultliteral alih-alih defaultoperator sehingga dapat dituliskan seperti di bawah ini:

v2 = v1 ?? default;
akesfeden
sumber
-1
 int v2= Int32.Parse(v1.ToString());
mohammad qavizi
sumber
5
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
xiawi
1
Lebih baik menggunakan cara "praktik terbaik" untuk membuka bungkusan opsional, daripada menggunakan trik curang. Lihat docs.microsoft.com/en-us/dotnet/csharp/language-reference/… untuk referensi
lorg
Ketika menjawab pertanyaan berusia delapan tahun dengan lima belas jawaban yang ada, penting untuk menjelaskan aspek baru dari pertanyaan yang Anda jawab, dan untuk mencatat jika perjalanan waktu telah mengubah jawaban. Kode hanya jawaban hampir selalu dapat ditingkatkan dengan penambahan beberapa penjelasan.
Jason Aller