Saya tidak mengerti kasus ini:
public delegate int test(int i);
public test Success()
{
Func<int, int> f = x => x;
return f.Invoke; // <- code successfully compiled
}
public test Fail()
{
Func<int, int> f = x => x;
return f; // <- code doesn't compile
}
Mengapa kompilasi OK ketika saya menggunakan Invoke
metode dan tidak OK ketika saya kembali csharp Func<int,int>
secara langsung?
delegate void test1(int i);
dandelegate void test2(int i);
Jawaban:
Ada dua hal yang perlu Anda ketahui untuk memahami perilaku ini.
System.Delegate
, tetapi delegasi yang berbeda memiliki tipe yang berbeda dan karenanya tidak dapat ditugaskan satu sama lain.Karena delegasi yang berbeda memiliki tipe yang berbeda, itu berarti Anda tidak dapat menetapkan delegasi dari satu tipe ke yang lain.
Misalnya, diberikan:
Kemudian:
Baris pertama di atas mengkompilasi OK karena menggunakan penanganan khusus untuk menetapkan lambda atau metode untuk delegasi.
Bahkan, baris ini ditulis ulang secara efektif seperti ini oleh kompiler:
Baris kedua di atas tidak dikompilasi karena sedang mencoba untuk menetapkan contoh dari satu jenis ke jenis lain yang tidak kompatibel.
Sejauh ini, tidak ada tugas yang kompatibel antara
test1
dantest2
karena mereka adalah tipe yang berbeda.Jika membantu untuk memikirkannya, pertimbangkan hierarki kelas ini:
Kode berikut TIDAK akan dikompilasi, meskipun
Test1
danTest2
berasal dari kelas dasar yang sama:Ini menjelaskan mengapa Anda tidak dapat menetapkan satu tipe delegasi ke yang lain. Itu hanya bahasa C # yang normal.
Namun, yang penting adalah untuk memahami mengapa Anda diizinkan untuk menetapkan metode atau lambda ke delegasi yang kompatibel. Seperti disebutkan di atas, ini adalah bagian dari dukungan bahasa C # untuk delegasi.
Jadi akhirnya untuk menjawab pertanyaan Anda:
Saat Anda menggunakan,
Invoke()
Anda menetapkan panggilan METHOD ke delegasi menggunakan penanganan bahasa C # khusus untuk menetapkan metode atau lambdas ke delegasi daripada mencoba untuk menetapkan tipe yang tidak kompatibel - karenanya dikompilasi OK.Agar benar-benar jelas, kode yang dikompilasi dalam OP Anda:
Sebenarnya dikonversi secara konseptual menjadi sesuatu seperti:
Sedangkan kode gagal berusaha untuk menetapkan antara dua jenis yang tidak kompatibel:
sumber
Dalam kasus kedua,
f
adalah tipeFunc<int, int>
, tetapi metode ini dikatakan mengembalikan atest
. Ini adalah tipe yang tidak terkait (mendelegasikan), yang tidak dapat dipertukarkan satu sama lain, sehingga terjadi kesalahan kompiler. Anda dapat pergi ke bagian spesifikasi bahasa ini, dan mencari "delegate". Anda tidak akan menemukan penyebutan konversi antara delegasi yang memiliki tanda tangan yang sama.Namun dalam kasus pertama,
f.Invoke
adalah ekspresi grup metode , yang sebenarnya tidak memiliki tipe. Compiler C # akan mengonversi ekspresi grup metode ke tipe delegasi tertentu sesuai dengan konteksnya, melalui konversi grup metode .(Mengutip peluru ke-5 di sini , penekanan milikku)
Dalam hal ini, itu dikonversi ke
test
tipe delegasi.Dengan kata lain,
return f
tidak berfungsi karenaf
sudah memiliki tipe, tetapif.Invoke
belum memiliki tipe.sumber
Masalah di sini adalah kompatibilitas Tipe:
Berikut ini adalah definisi delegasi Func dari Sumber MSDN:
public delegate TResult Func<in T, out TResult>(T arg);
Jika Anda melihat tidak ada hubungan langsung antara Fungsi yang disebutkan di atas dan Delegasi yang Anda tentukan:
public delegate int test(int i);
Delegasi dibandingkan menggunakan tanda tangan, yang merupakan parameter input dan hasil Output, akhirnya seorang Delegasi adalah pointer Fungsi dan dua fungsi dapat dibandingkan hanya melalui tanda tangan. Pada saat runtime, metode yang dipanggil melalui Func ditugaskan ke
Test
delegasi, karena Signature sama berfungsi dengan mulus. Ini adalah penunjuk fungsi, di manaTest
delegasi sekarang akan memanggil metode yang ditunjuk oleh delegasi FuncAntara Func dan delegasi uji, tidak ada kompatibilitas jenis / penugasan, Func tidak dapat mengisi sebagai bagian dari aturan sistem Type. Bahkan ketika hasilnya dapat ditugaskan dan diisi
test delegate
seperti yang dilakukan pada kasus pertama.sumber