Berlari melintasi baris kode ini:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Apa arti dari dua tanda tanya, apakah itu semacam operator ternary? Sulit untuk mencari di Google.
Berlari melintasi baris kode ini:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Apa arti dari dua tanda tanya, apakah itu semacam operator ternary? Sulit untuk mencari di Google.
Jawaban:
Ini adalah operator penggabungan nol, dan sangat mirip dengan operator ternary (langsung-jika). Lihat juga ?? Operator - MSDN .
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
memperluas ke:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
yang selanjutnya berkembang menjadi:
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
Dalam bahasa Inggris, itu berarti "Jika apa pun yang ada di sebelah kiri bukan nol, gunakan itu, kalau tidak gunakan apa yang ke kanan."
Perhatikan bahwa Anda dapat menggunakan nomor-nomor ini secara berurutan. Pernyataan berikut akan menetapkan non-null pertama Answer#
ke Answer
(jika semua Jawaban adalah nol maka itu Answer
adalah nol):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
Juga perlu disebutkan sementara ekspansi di atas secara konseptual setara, hasil dari setiap ekspresi hanya dievaluasi satu kali. Ini penting jika misalnya ekspresi adalah pemanggilan metode dengan efek samping. (Kredit untuk @ Joey karena menunjukkan ini.)
??
adalah asosiatif kiri, jadi a ?? b ?? c ?? d
sama dengan ((a ?? b) ?? c ) ?? d
. "Operator penugasan dan operator ternary (? :) adalah asosiatif yang tepat. Semua operator biner lainnya adalah asosiatif kiri." Sumber: msdn.microsoft.com/en-us/library/ms173145.aspx
Hanya karena tidak ada orang lain yang mengucapkan kata-kata ajaib: itu adalah operator penggabungan nol . Ini didefinisikan dalam bagian 7.12 dari spesifikasi bahasa C # 3.0 .
Ini sangat berguna, terutama karena cara kerjanya ketika digunakan beberapa kali dalam ekspresi. Ekspresi bentuk:
a ?? b ?? c ?? d
akan memberikan hasil ekspresi a
jika tidak nol, jika tidak coba b
, jika tidak coba c
, jika tidak coba d
. Ini korsleting di setiap titik.
Juga, jika jenis d
tidak dapat dibatalkan, jenis seluruh ekspresi juga tidak dapat dibatalkan.
Ini operator penggabungan nol.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
Ya, hampir mustahil untuk mencari kecuali Anda tahu apa namanya! :-)
EDIT: Dan ini adalah fitur keren dari pertanyaan lain. Anda bisa merantai mereka.
Terima kasih semuanya, berikut adalah penjelasan paling ringkas yang saya temukan di situs MSDN:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
-1
hanya sebuah dataran int
, yang tidak dapat dibatalkan).
x
tipe int?
, tetapi y
tipe int
, Anda bisa menulis int y = (int)(x ?? -1)
. Ini akan diuraikan x
menjadi int
jika tidak null
, atau ditugaskan -1
ke y
jika x
tidak null
.
Dua tanda tanya (??) menunjukkan bahwa ini adalah operator Penggabungan.
Operator penggabungan mengembalikan nilai NON-NULL pertama dari sebuah rantai. Anda dapat melihat video youtube ini yang menunjukkan semuanya secara praktis.
Tetapi izinkan saya menambahkan lebih banyak pada apa yang dikatakan video.
Jika Anda melihat arti bahasa Inggris penggabungan itu mengatakan "konsolidasi bersama". Sebagai contoh di bawah ini adalah kode penggabungan sederhana yang menghubungkan empat string.
Jadi jika str1
ini null
ia akan mencoba str2
, jika str2
ini null
ia akan mencoba str3
dan seterusnya sampai menemukan string dengan nilai non-null.
string final = str1 ?? str2 ?? str3 ?? str4;
Dengan kata sederhana, operator Penggabungan mengembalikan nilai NON-NULL pertama dari sebuah rantai.
Ini tangan pendek untuk operator ternary.
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
Atau bagi mereka yang tidak melakukan ternary:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
) dan yang kedua formsAuth
(setelah ?
) dapat diubah; dalam bentuk penggabungan nol, keduanya secara implisit mengambil nilai yang Anda berikan.
Jika Anda terbiasa dengan Ruby, ||=
sepertinya mirip dengan C # ??
bagi saya. Ini beberapa Ruby:
irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"
Dan di C #:
string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
x ||= y
desugars ke sesuatu seperti x = x || y
, jadi ??
sebenarnya lebih mirip dengan polos ||
di Ruby.
??
hanya peduli tentang null
, sedangkan ||
operator dalam Ruby, seperti dalam kebanyakan bahasa, adalah tentang null
, false
, atau apapun yang dapat dianggap sebagai boolean dengan nilai false
(misalnya dalam beberapa bahasa, ""
). Ini bukan hal yang baik atau buruk, hanya perbedaan.
Tidak ada yang berbahaya tentang ini. Padahal, itu indah. Anda dapat menambahkan nilai default jika diinginkan, misalnya:
KODE
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
Apakah itu benar
x1
- x4
HARUS menjadi jenis yang dapat dibatalkan : tidak masuk akal untuk mengatakan, secara efektif, "hasilnya adalah 0
jika x4
nilai yang tidak mungkin diambil" ( null
). "Jenis yang dapat dihapus" di sini mencakup jenis nilai yang dapat dibatalkan dan jenis referensi, tentu saja. Ini adalah kesalahan waktu kompilasi jika satu atau lebih variabel dirantai (kecuali yang terakhir) tidak dapat dibatalkan.
Seperti yang ditunjukkan dengan benar dalam berbagai jawaban yang merupakan "operator penggabungan nol" ( ?? ), yang berbicara tentang Anda mungkin juga ingin memeriksa sepupunya "Operator Bersyarat Null" ( ?. Atau ? [ ) Yang merupakan operator yang banyak kali digunakan dalam hubungannya dengan ??
Digunakan untuk menguji nol sebelum melakukan operasi akses anggota ( ? ) Atau indeks ( ? [ ). Operator-operator ini membantu Anda menulis lebih sedikit kode untuk menangani cek nol, terutama untuk turun ke struktur data.
Sebagai contoh:
// if 'customers' or 'Order' property or 'Price' property is null,
// dollarAmount will be 0
// otherwise dollarAmount will be equal to 'customers.Order.Price'
int dollarAmount = customers?.Order?.Price ?? 0;
cara lama tanpa ? dan ?? melakukan ini
int dollarAmount = customers != null
&& customers.Order!=null
&& customers.Order.Price!=null
? customers.Order.Price : 0;
yang lebih verbose dan rumit.
Hanya untuk hiburan Anda (mengetahui bahwa Anda semua adalah C # guys ;-).
Saya pikir itu berasal dari Smalltalk, di mana sudah ada selama bertahun-tahun. Di sana didefinisikan sebagai:
di Object:
? anArgument
^ self
di UndefinedObject (kelas alias nil):
? anArgument
^ anArgument
Ada versi yang mengevaluasi (?) Dan versi yang tidak mengevaluasi (??).
Hal ini sering ditemukan dalam metode getter untuk variabel privat (contoh) malas yang diinisialisasi, yang dibiarkan nol hingga benar-benar diperlukan.
Beberapa contoh di sini tentang mendapatkan nilai menggunakan penggabungan tidak efisien.
Yang benar-benar Anda inginkan adalah:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
atau
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
Ini mencegah objek dari diciptakan kembali setiap waktu. Alih-alih variabel pribadi yang tersisa nol dan objek baru dibuat pada setiap permintaan, ini memastikan variabel pribadi ditugaskan jika objek baru dibuat.
??
jalan pintas dievaluasi? new FormsAuthenticationWrapper();
dievaluasi jika dan hanya jika _formsAuthWrapper
nihil.
Saya telah membaca seluruh utas ini dan banyak lainnya, tetapi saya tidak dapat menemukan jawaban selengkap ini.
Dengan mana saya benar-benar mengerti "mengapa harus menggunakan ?? dan kapan harus menggunakan ?? dan bagaimana cara menggunakan ??."
Yayasan komunikasi Windows dilepaskan Oleh Craig McMurtry ISBN 0-672-32948-4
Ada dua keadaan umum di mana seseorang ingin tahu apakah suatu nilai telah ditetapkan untuk sebuah instance dari tipe nilai. Yang pertama adalah ketika instance mewakili nilai dalam database. Dalam kasus seperti itu, seseorang ingin dapat memeriksa contoh untuk memastikan apakah suatu nilai memang ada dalam database. Keadaan lain, yang lebih berkaitan dengan pokok bahasan buku ini, adalah ketika instance mewakili item data yang diterima dari beberapa sumber jarak jauh. Sekali lagi, orang ingin menentukan dari contoh apakah nilai untuk item data itu diterima.
.NET Framework 2.0 menggabungkan definisi tipe generik yang menyediakan untuk kasus-kasus seperti ini di mana seseorang ingin menetapkan nol untuk turunan dari tipe nilai, dan menguji apakah nilai turunannya nol. Definisi tipe generik itu adalah System.Nullable, yang membatasi argumen tipe generik yang dapat diganti dengan T untuk tipe nilai. Contoh tipe yang dibangun dari System.Nullable dapat diberi nilai nol; memang, nilai-nilai mereka adalah null secara default. Dengan demikian, tipe yang dibangun dari System.Nullable dapat disebut sebagai tipe nilai yang dapat dibatalkan. System.Nullable memiliki properti, Value, di mana nilai yang ditetapkan untuk sebuah instance dari tipe yang dibangun darinya dapat diperoleh jika nilai instance tidak nol. Karena itu, seseorang dapat menulis:
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
Bahasa pemrograman C # menyediakan sintaks yang disingkat untuk mendeklarasikan tipe yang dibangun dari System.Nullable. Sintaksis itu memungkinkan seseorang untuk menyingkat:
System.Nullable<int> myNullableInteger;
untuk
int? myNullableInteger;
Kompiler akan mencegah seseorang dari mencoba untuk menetapkan nilai tipe nilai nullable ke tipe nilai biasa dengan cara ini:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
Ini mencegah seseorang dari melakukan hal itu karena tipe nilai nullable dapat memiliki nilai null, yang sebenarnya akan terjadi dalam kasus ini, dan nilai itu tidak dapat ditugaskan ke tipe nilai biasa. Meskipun kompiler akan mengizinkan kode ini,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
Pernyataan kedua akan menyebabkan pengecualian untuk dilempar karena setiap upaya untuk mengakses properti System.Nullable.Value adalah operasi yang tidak valid jika tipe yang dibangun dari System.Nullable belum diberi nilai T yang valid, yang belum terjadi dalam hal ini. kasus.
Salah satu cara yang tepat untuk menetapkan nilai tipe nilai nullable ke tipe nilai biasa adalah dengan menggunakan properti System.Nullable.HasValue untuk memastikan apakah nilai T yang valid telah ditetapkan ke tipe nilai nullable:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
Opsi lain adalah menggunakan sintaks ini:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
Dengan mana integer biasa myInteger diberi nilai integer nullable "myNullableInteger" jika yang terakhir telah diberi nilai integer yang valid; jika tidak, myInteger diberi nilai -1.
Ini adalah operator penggabungan nol yang bekerja sama dengan operator ternary.
a ?? b => a !=null ? a : b
Hal lain yang menarik untuk ini adalah, "Tipe yang dapat dibatalkan dapat berisi nilai, atau dapat ditentukan" . Jadi, jika Anda mencoba menetapkan tipe nilai nullable ke tipe nilai non-nullable Anda akan mendapatkan kesalahan waktu kompilasi.
int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.
Jadi untuk melakukan itu menggunakan ?? operator:
z = x ?? 1; // with ?? operator there are no issues
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
setara dengan
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
Tapi yang paling keren dari itu adalah Anda bisa memeluk mereka, seperti kata orang lain. Satu yang tidak disentuh adalah bahwa Anda benar-benar dapat menggunakannya untuk melempar pengecualian.
A = A ?? B ?? throw new Exception("A and B are both NULL");
The ??
operator disebut operator null-penggabungan. Ini mengembalikan operan kiri jika operan tidak nol; jika tidak mengembalikan operan kanan.
int? variable1 = null;
int variable2 = variable1 ?? 100;
Setel variable2
ke nilai variable1
, jika variable1
TIDAK nol; jika tidak, jika variable1 == null
diatur variable2
ke 100.
Yang lain menggambarkannya dengan Null Coalescing Operator
cukup baik. Bagi yang berminat, ada sintaks singkat di mana ini (pertanyaan SO):
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
setara dengan ini:
FormsAuth ??= new FormsAuthenticationWrapper();
Beberapa merasa lebih mudah dibaca dan ringkas.