Apa yang dimaksud dengan operator tanda dan titik tanya? artinya dalam C # 6.0?

359

Dengan C # 6.0 dalam pratinjau VS2015 kami memiliki operator baru ?., yang dapat digunakan seperti ini:

public class A {
   string PropertyOfA { get; set; }
}

...

var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
   //somecode
}

Apa fungsinya?

Landeeyo
sumber

Jawaban:

500

Ini adalah operator kondisional nol . Ini pada dasarnya berarti:

"Evaluasi operan pertama; jika itu nol, hentikan, dengan hasil nol. Kalau tidak, evaluasi operan kedua (sebagai akses anggota dari operan pertama)."

Dalam contoh Anda, intinya adalah bahwa jika aini null, maka a?.PropertyOfAakan mengevaluasi ke nulldaripada membuang pengecualian - kemudian akan membandingkan bahwa nullreferensi dengan foo(menggunakan string ==yang berlebihan), menemukan mereka tidak sama dan eksekusi akan masuk ke tubuh ifpernyataan .

Dengan kata lain, seperti ini:

string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
    ...
}

... kecuali itu ahanya dievaluasi sekali.

Perhatikan bahwa ini juga dapat mengubah jenis ekspresi. Sebagai contoh, pertimbangkan FileInfo.Length. Itu properti tipe long, tetapi jika Anda menggunakannya dengan operator kondisional nol, Anda berakhir dengan ekspresi tipe long?:

FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
Jon Skeet
sumber
8
Bukankah itu disebut operator kondisional nol ?
SLaks
1
@ SLaks: Saya pikir itu "conditional null" tapi saya bisa saja salah. Terakhir kali saya memeriksa dokumen fitur bahasa Roslyn, itu belum diganti namanya juga. Mungkin sumbernya adalah otoritas di sini - akan memeriksa.
Jon Skeet
3
@SLaks: Tentu. Dalam SyntaxKind itu tampaknya ConditionalAccessExpression yang tidak mengganggu mereka ...
Jon Skeet
12
Saya lebih suka nama "Elvis" operator: P
Ahmed ilyas
3
Sebagai catatan saya telah melihat lima nama berbeda untuk operator ini: navigasi yang aman, null-conditional, null propagation, conditional access, Elvis.
Gigi
81

Ini bisa sangat berguna ketika meratakan sebuah hierarki dan / atau memetakan objek. Dari pada:

if (Model.Model2 == null
  || Model.Model2.Model3 == null
  || Model.Model2.Model3.Model4 == null
  || Model.Model2.Model3.Model4.Name == null)
{
  mapped.Name = "N/A"
}
else
{
  mapped.Name = Model.Model2.Model3.Model4.Name;
}

Itu dapat ditulis seperti (logika yang sama seperti di atas)

mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";

Contoh Kerja DotNetFiddle.Net .

( operator ?? atau null-coalescing berbeda dari operator kondisional? atau null ).

Itu juga dapat digunakan di luar operator penugasan dengan Action. Dari pada

Action<TValue> myAction = null;

if (myAction != null)
{
  myAction(TValue);
}

Ini dapat disederhanakan untuk:

myAction?.Invoke(TValue);

Contoh DotNetFiddle :

menggunakan Sistem;

public class Program
{
  public static void Main()
  {
    Action<string> consoleWrite = null;

    consoleWrite?.Invoke("Test 1");

    consoleWrite = (s) => Console.WriteLine(s);

    consoleWrite?.Invoke("Test 2");
  }
}

Hasil:

Tes 2

Erik Philips
sumber
27
Untuk menyelamatkan orang mencari apa ?? adalah .. Ini adalah operator penggabungan nol dan akan mengembalikan Nama jika bukan nol, jika tidak maka akan mengembalikan "N / A".
Steve
6
@Erik Philips Saya pikir Anda perlu menambahkan || Model.Model2.Model3.Model4.Name == null untuk memiliki logika yang sama, jika tidak, dalam kasus Model.Model2.Model3.Model4.Nameini null, mapped.Nameakan tetapnull
RazvanR
2
@ErikPhilips Tidak di halaman yang sama kurasa. Coba lihat apa yang terjadi pada kedua kasus Anda jika Model.Model2.Model3.Model4.Nameada null.
RazvanR
1
Hasilnya adalah "N / A", sekali lagi HARAP BACA KOMENTAR PERTAMA. Contoh Kerja DotNetFiddle.Net .
Erik Philips
7
@ErikPhilips: Itu tidak ada hubungannya dengan komentar pertama, karena ini tidak berhubungan dengan contoh pertama Anda. Dalam hal ini Anda akan melompat ke- elsecabang dan miliki mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, sedangkan contoh kedua Anda akan menggantikan mapped.Name = "N/A". Lihat diedit DotNetFiddle
Derm
3

Ini relatif baru untuk C # yang membuatnya mudah bagi kita untuk memanggil fungsi sehubungan dengan nilai-nilai nol atau non-nol dalam metode chaining.

cara lama untuk mencapai hal yang sama adalah:

var functionCaller = this.member;
if (functionCaller!= null)
    functionCaller.someFunction(var someParam);

dan sekarang telah dibuat lebih mudah hanya dengan:

member?.someFunction(var someParam);

Saya sangat menyarankan Anda untuk membacanya di sini:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

Zeeshan Adil
sumber