Tentunya alasan sebenarnya untuk menggunakan Func
alih-alih delegasi tertentu adalah bahwa C # memperlakukan delegasi yang dideklarasikan secara terpisah sebagai tipe yang sama sekali berbeda.
Meskipun Func<int, bool>
dan Predicate<int>
keduanya memiliki argumen dan tipe pengembalian yang sama, keduanya tidak kompatibel dengan penugasan. Jadi jika setiap perpustakaan mendeklarasikan tipe delegasinya sendiri untuk setiap pola delegasi, perpustakaan tersebut tidak akan dapat beroperasi kecuali pengguna memasukkan "bridging" delegate untuk melakukan konversi.
// declare two delegate types, completely identical but different names:
public delegate void ExceptionHandler1(Exception x);
public delegate void ExceptionHandler2(Exception x);
// a method that is compatible with either of them:
public static void MyExceptionHandler(Exception x)
{
Console.WriteLine(x.Message);
}
static void Main(string[] args)
{
// can assign any method having the right pattern
ExceptionHandler1 x1 = MyExceptionHandler;
// and yet cannot assign a delegate with identical declaration!
ExceptionHandler2 x2 = x1; // error at compile time
}
Dengan mendorong semua orang untuk menggunakan Fungsi, Microsoft berharap ini akan mengurangi masalah tipe delegasi yang tidak kompatibel. Delegasi setiap orang akan bermain bersama dengan baik, karena mereka hanya akan dicocokkan berdasarkan pada parameter / tipe pengembalian mereka.
Itu tidak menyelesaikan semua masalah, karena Func
(dan Action
) tidak dapat memiliki out
atau ref
parameter, tetapi mereka kurang umum digunakan.
Pembaruan: dalam komentar Svish mengatakan:
Namun, beralih jenis parameter dari Func ke Predicate dan kembali, sepertinya tidak ada bedanya? Setidaknya masih dikompilasi tanpa masalah.
Ya, selama program Anda hanya menetapkan metode untuk didelegasikan, seperti pada baris pertama dari Main
fungsi saya . Kompiler secara diam-diam menghasilkan kode ke objek delegasi baru yang meneruskan ke metode. Jadi dalam Main
fungsi saya , saya bisa berubah x1
menjadi tipe ExceptionHandler2
tanpa menyebabkan masalah.
Namun, pada baris kedua saya mencoba untuk menetapkan delegasi pertama ke delegasi lain. Bahkan berpikir bahwa tipe delegasi ke-2 memiliki parameter yang persis sama dan tipe yang dikembalikan, kompiler memberikan kesalahan CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'
.
Mungkin ini akan membuatnya lebih jelas:
public static bool IsNegative(int x)
{
return x < 0;
}
static void Main(string[] args)
{
Predicate<int> p = IsNegative;
Func<int, bool> f = IsNegative;
p = f; // Not allowed
}
Metode saya IsNegative
adalah hal yang sangat baik untuk ditugaskan ke p
dan f
variabel, selama saya melakukannya secara langsung. Tapi kemudian saya tidak bisa menetapkan salah satu variabel tersebut ke yang lain.