<int> vs. int? - Apa ada bedanya?

93

Tampaknya Nullable<int>dan int?nilainya setara. Apakah ada alasan untuk memilih salah satu dari yang lain?

Nullable<int> a = null;
int? b = null;
a == b; // this is true
Zachary Scott
sumber

Jawaban:

135

Tidak ada perbedaan.

int?hanyalah singkatan dari Nullable<int>, yang dengan sendirinya merupakan singkatan dari Nullable<Int32>.

Kode yang dikompilasi akan persis sama dengan yang Anda pilih untuk digunakan.

LukeH
sumber
1
Sayangnya ada beberapa kasus sudut ketika ini tidak sepenuhnya benar. Lihat jawaban ini .
qqbenq
22

The ?bentuk hanya singkatan untuk jenis penuh. Preferensi pribadi adalah satu-satunya alasan untuk memilih satu di antara yang lain.

Detail lengkapnya di sini .

Sintaksnya T?adalah singkatan dari Nullable<T>, di mana Tadalah tipe nilai. Kedua bentuk tersebut dapat dipertukarkan.

Steve Townsend
sumber
18

Sementara saya sepenuhnya setuju bahwa dalam kebanyakan kasus mereka adalah sama, saya baru-baru datang di sebuah situasi, ketika ada adalah perbedaan antara kedua. Untuk detail yang mengerikan lihat pertanyaan ini , tetapi untuk memberi Anda contoh singkat di sini:

void Test<T>(T a, bool b)
{
    var test = a is int? & b;              // does not compile
    var test2 = a is Nullable<int> & b;    // does compile
}

Baris pertama memberikan pesan kesalahan berikut:

error CS1003: Syntax error, ':' expected 
error CS1525: Invalid expression term ';'

Jika Anda penasaran dengan alasan pasti untuk ini, saya sangat menyarankan Anda untuk memeriksa pertanyaan yang sudah ditautkan , tetapi masalah dasarnya adalah bahwa dalam fase penguraian setelah operator is(atau as), ketika kita menghadapi ?token, kita memeriksa apakah yang berikutnya token dapat diartikan sebagai operator unary ( &bisa jadi satu) dan jika demikian: parser tidak peduli tentang kemungkinan ?token menjadi pengubah tipe, ia hanya menggunakan tipe sebelumnya, dan akan mengurai sisanya seolah-olah ?token adalah operator terner (sehingga penguraian akan gagal).

Jadi, meskipun secara umum int?dan Nullable<int>dapat dipertukarkan, ada beberapa kasus sudut ketika menghasilkan hasil yang sangat berbeda, karena cara parser melihat kode Anda.

qqbenq.dll
sumber
2
Kasus pertama,, testdiperbaiki dengan tanda kurung, jadi var test = (a is int?) & b;. Bisa juga diperbaiki dengan var test = a is int? && b;, dan mengingat bahwa badalah parameter nilai sederhana (tidak ada efek samping pada evaluasi) tampaknya aneh untuk memilih &lebih &&.
Jeppe Stig Nielsen
Dalam sintaks khusus itu, ?adalah karakter kunci.
Pete Garafano
Lihat pertanyaan dan jawaban yang ditautkan, semua komentar Anda ditujukan di sana :) Saya baru saja menambahkan info ini di sini, karena menurut saya info ini relevan, karena menampilkan perbedaan antara kedua bentuk, dan membuktikan bahwa ini bukan hanya gula sintaksis
qqbenq
Jeppe benar. Ini tidak dikompilasi karena menafsirkan int?sebagai operasi terner ( var test = a is int? <return if true> : <return if false>), bukan int nullable.
Levi Fuller
1
@LeviFuller (lanjutan) Lihat dokumentasi untuk boolkelebihan beban tertentu ini . Ini adalah operator logika Boolean ( &untuk bool) dan operator logika bersyarat Boolean ( &&untuk bool). Perhatikan bagaimana subbagian pertama ini dengan jelas dinamai logis . Ingat, di C # tidak ada konversi ("cast") antara booldan tipe numerik!
Jeppe Stig Nielsen
6

Tampaknya ada perbedaan antara keduanya saat menggunakan pembuatan Code-first Entity Framework (EF):

Ketika entitas Anda berisi properti yang dinyatakan seperti:

public class MyEntity
{
    public Nullable<int> MyNullableInt { get; set; } 
}

EF tidak akan menghasilkan properti nullable dan Anda harus memaksa generator untuk menjadikannya nullable seperti:

public class YourContext : DbContext
{
    public DbSet<MyEntity> MyEntities{ get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<MyEntity>().Property(x => x.MyNullableInt).IsOptional();
    }
}

Di sisi lain, jika Anda mendeklarasikan entitas Anda seperti:

public class MyEntity
{
     public int? MyNullableInt { get; set; }
}

generator EF akan menghasilkan properti nullable dengan kolom nullable di tabel database terkait.

Maciej
sumber
2
Sangat disayangkan.
siride
8
Itu menunjukkan Anda memiliki beberapa Nullabledefinisi lain di suatu tempat, karena dengan built-in Nullable<T>, EF tidak mungkin melihat perbedaan antara keduanya. Bahkan jika orang-orang EF ingin memperlakukan mereka secara berbeda, mereka tidak bisa.
1
Sudahkah seseorang mengkonfirmasi ini masalahnya? (hanya sedikit berhati-hati karena suara negatif)
RayLoveless
@RayL Tidak ini bukan masalahnya. Jawaban ini tidak benar dan seperti yang ditunjukkan oleh hvd, tidak mungkin.
Sepatu
1
Mempertimbangkan bahwa kode EF dibuat menggunakan templat kode, hal ini mungkin saja terjadi. Jawaban saya didasarkan pada pengalaman saya dan perubahan yang saya sarankan untuk memperbaiki masalah yang saya alami. Selain itu, tampaknya sebagian orang menemukan bahwa hal tersebut memang merupakan kasus berdasarkan suara terbanyak.
Maciej
2

Nullable adalah tipe generik, tapi int? tidak.

Ada beberapa skenario di mana Nullable harus digunakan melalui int?

misalnya: di sini Anda tidak dapat mengganti Nullable dengan int?

bagaimana Anda bisa mengubah kode di bawah ini tanpa menggunakan Nullable ?

class LazyValue<T> where T : struct
{
   private Nullable<T> val;
   private Func<T> getValue;

   // Constructor.
   public LazyValue(Func<T> func)
   {
      val = null;
      getValue = func;
   }

   public T Value
   {
      get
      {
         if (val == null)
            // Execute the delegate.
            val = getValue();
         return (T)val;
      }
   }
}
Rajes
sumber
3
Yang mungkin penting jika pertanyaannya menanyakan tentang tipe generik, tetapi pertanyaannya telah menentukan int, jadi bukan Nullable<T>ituNullable<int>
Andrew