Ada pola dalam kelas C # yang dicontohkan oleh Dictionary.TryGetValue
dan int.TryParse
: metode yang mengembalikan boolean yang menunjukkan keberhasilan operasi dan parameter keluar yang berisi hasil aktual; jika operasi gagal, parameter keluar diatur ke nol.
Mari kita asumsikan saya menggunakan referensi non-nullable C # 8 dan ingin menulis metode TryParse untuk kelas saya sendiri. Tanda tangan yang benar adalah ini:
public static bool TryParse(string s, out MyClass? result);
Karena hasilnya nol dalam kasus palsu, variabel keluar harus ditandai sebagai nullable.
Namun, pola Coba umumnya digunakan seperti ini:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
Karena saya hanya memasuki cabang ketika operasi berhasil, hasilnya tidak boleh nol di cabang itu. Tetapi karena saya menandainya sebagai nullable, sekarang saya harus memeriksa atau menggunakannya !
untuk mengganti:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // compiler warning, could be null
Console.WriteLine("Look: {0}", result!.SomeProperty); // need override
}
Ini jelek dan agak tidak ekonomis.
Karena pola penggunaan yang umum, saya memiliki pilihan lain: berbohong tentang jenis hasil:
public static bool TryParse(string s, out MyClass result) // not nullable
{
// Happy path sets result to non-null and returns true.
// Error path does this:
result = null!; // override compiler complaint
return false;
}
Sekarang penggunaan tipikal menjadi lebih baik:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
tetapi penggunaan yang tidak biasa tidak mendapatkan peringatan yang seharusnya:
else
{
Console.WriteLine("Fail: {0}", result.SomeProperty);
// Yes, result is in scope here. No, it will never be non-null.
// Yes, it will throw. No, the compiler won't warn about it.
}
Sekarang saya tidak yakin ke mana harus pergi ke sini. Apakah ada rekomendasi resmi dari tim bahasa C #? Apakah ada kode CoreFX yang telah dikonversi menjadi referensi yang tidak dapat dibatalkan yang dapat menunjukkan kepada saya bagaimana melakukan ini? (Saya pergi mencari TryParse
metode. IPAddress
Adalah kelas yang memiliki satu, tetapi belum dikonversi pada cabang utama corefx.)
Dan bagaimana kode generik suka Dictionary.TryGetValue
menangani ini? (Mungkin dengan MaybeNull
atribut khusus dari apa yang saya temukan.) Apa yang terjadi ketika saya instantiate Dictionary
dengan tipe nilai yang tidak dapat dibatalkan?
MyClass?
), dan lakukan sakelar dengan acase MyClass myObj:
dan (sebuah opsi semua)case null:
.