TLDR: Ini adalah bug yang dikenal lama. Saya pertama kali menulis tentang hal itu pada tahun 2010:
https://blogs.msdn.microsoft.com/ericlippert/2010/01/18/a-definite-assignment-anomaly/
Ini tidak berbahaya dan Anda dapat dengan aman mengabaikannya, dan memberi selamat pada diri sendiri karena menemukan bug yang agak kabur.
Mengapa kompiler tidak menjalankan yang Emailharus ditentukan?
Oh, benar, dengan cara. Itu hanya memiliki ide yang salah tentang kondisi apa yang menyiratkan bahwa variabel pasti ditugaskan, seperti yang akan kita lihat.
Mengapa kode ini dikompilasi jika struct dibuat dalam rakitan yang terpisah, tetapi tidak mengkompilasi jika struct didefinisikan dalam rakitan yang ada?
Itulah inti dari bug. Bug adalah konsekuensi dari persimpangan bagaimana C # compiler melakukan pengecekan tugas yang pasti pada struct dan bagaimana kompiler memuat metadata dari perpustakaan.
Pertimbangkan ini:
struct Foo
{
public int x;
public int y;
}
// Yes, public fields are bad, but this is just
// to illustrate the situation.
void M(out Foo f)
{
OKE, pada titik ini apa yang kita ketahui? fadalah alias untuk variabel tipe Foo, jadi penyimpanan telah dialokasikan dan jelas setidaknya dalam keadaan keluar dari alokasi penyimpanan. Jika ada nilai yang ditempatkan dalam variabel oleh pemanggil, nilai itu ada di sana.
Apa yang kami butuhkan? Kami mengharuskan yang fpasti ditugaskan pada setiap titik di mana kontrol berjalan Mnormal. Jadi Anda akan mengharapkan sesuatu seperti:
void M(out Foo f)
{
f = new Foo();
}
yang menetapkan f.xdan f.yke nilai standarnya. Tapi bagaimana dengan ini?
void M(out Foo f)
{
f = new Foo();
f.x = 123;
f.y = 456;
}
Itu juga harus baik-baik saja. Tapi, dan inilah kickernya, mengapa kita perlu menetapkan nilai default hanya untuk melenyapkannya beberapa saat kemudian? Pemeriksa penugasan tugas pasti C # memeriksa untuk melihat apakah setiap bidang ditugaskan! Ini legal:
void M(out Foo f)
{
f.x = 123;
f.y = 456;
}
Dan mengapa itu tidak legal? Ini adalah tipe nilai. fadalah variabel, dan sudah berisi nilai jenis yang valid Foo, jadi mari kita atur bidang, dan kita selesai, kan?
Baik. Jadi, apa masalahnya?
Bug yang Anda temukan adalah: sebagai penghematan biaya, kompiler C # tidak memuat metadata untuk bidang pribadi struct yang ada di perpustakaan yang dirujuk . Metadata itu bisa sangat besar , dan itu akan memperlambat kompiler untuk kemenangan yang sangat kecil untuk memuat semuanya ke dalam memori setiap waktu.
Dan sekarang Anda harus dapat menyimpulkan penyebab bug yang Anda temukan. Ketika kompilator memeriksa untuk melihat apakah parameter keluar ditetapkan dengan pasti, ia membandingkan jumlah bidang yang diketahui dengan jumlah bidang yang ditentukan diinisialisasi dan dalam kasus Anda hanya tahu tentang bidang publik nol karena metadata bidang pribadi tidak dimuat . Kompilator menyimpulkan "nol bidang wajib diisi, nol bidang diinisialisasi, kami baik."
Seperti yang saya katakan, bug ini telah ada selama lebih dari satu dekade dan orang-orang seperti Anda kadang-kadang menemukan kembali dan melaporkannya. Ini tidak berbahaya, dan tidak mungkin diperbaiki karena memperbaikinya hampir tidak menguntungkan tetapi biaya kinerja yang besar.
Dan tentu saja bug tersebut tidak repro untuk bidang priv dari struct yang ada dalam kode sumber dalam proyek Anda, karena jelas kompiler sudah memiliki informasi tentang bidang pribadi yang ada.