Ada dua hal yang perlu Anda ketahui untuk memahami perilaku ini.
- Semua delegasi berasal
System.Delegate
, tetapi delegasi yang berbeda memiliki tipe yang berbeda dan karenanya tidak dapat ditugaskan satu sama lain.
- Bahasa C # menyediakan penanganan khusus untuk menetapkan metode atau lambda ke delegasi .
Karena delegasi yang berbeda memiliki tipe yang berbeda, itu berarti Anda tidak dapat menetapkan delegasi dari satu tipe ke yang lain.
Misalnya, diberikan:
delegate void test1(int i);
delegate void test2(int i);
Kemudian:
test1 a = Console.WriteLine; // Using special delegate initialisation handling.
test2 b = a; // Using normal assignment, therefore does not compile.
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:
test1 a = new test1(Console.WriteLine);
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:
class Base
{
}
class Test1 : Base
{
}
class Test2 : Base
{
}
Kode berikut TIDAK akan dikompilasi, meskipun Test1
dan Test2
berasal dari kelas dasar yang sama:
Test1 test1 = new Test1();
Test2 test2 = test1; // Compile error.
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:
public test Success()
{
Func<int, int> f = x => x;
return f.Invoke; // <- code successfully compiled
}
Sebenarnya dikonversi secara konseptual menjadi sesuatu seperti:
public test Success()
{
Func<int, int> f = x => x;
return new test(f.Invoke);
}
Sedangkan kode gagal berusaha untuk menetapkan antara dua jenis yang tidak kompatibel:
public test Fail()
{
Func<int, int> f = x => x;
return f; // Attempting to assign one delegate type to another: Fails
}