Kesinlikle Func
belirli bir delege kullanmak için asıl neden , C #'ın ayrı ayrı beyan edilen delegelere tamamen farklı türler olarak davranmasıdır.
Olsa Func<int, bool>
ve Predicate<int>
her ikisi aynı argüman ve dönüş türleri vardır, bunlar atama-uyumlu değildir. Dolayısıyla, her kütüphane her delege kalıbı için kendi temsilci türünü bildirirse, kullanıcı dönüşümleri gerçekleştirmek için "köprüleme" delegeleri eklemediği sürece bu kütüphaneler birlikte çalışamaz.
// 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
}
Microsoft, herkesi Func'u kullanmaya teşvik ederek bunun uyumsuz delege türleri sorununu hafifleteceğini umuyor. Herkesin delegeleri güzelce birlikte oynayacaklar, çünkü sadece parametre / dönüş türlerine göre eşleştirilecekler.
Tüm problemleri çözmez, çünkü Func
(ve Action
) sahip olamaz out
veya ref
parametreler olamaz , ancak bunlar daha az kullanılır.
Güncelleme: yorumlarda Svish diyor:
Yine de, Func'tan Predicate ve Back'e bir parametre türünü değiştirmek herhangi bir fark yaratmıyor mu? En azından hala sorunsuz derliyor.
Evet, programınız Main
işlevimin ilk satırında olduğu gibi yalnızca delegelere yöntem atarsa . Derleyici, yönteme ileten yeni bir temsilci nesnesine sessizce kod üretir. Yani benim Main
fonksiyonumda, bir soruna neden olmadan x1
türünü değiştirebilirim ExceptionHandler2
.
Ancak, ikinci satırda ilk delege başka bir delege atamaya çalışıyorum. 2. delege türünün tamamen aynı parametre ve dönüş türlerine sahip olduğu düşünüldüğünde bile, derleyici hata verirCS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'
.
Belki bu daha açık hale getirecektir:
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
}
Benim yöntemim ve değişkenlere IsNegative
atamak için mükemmel bir şey . Ama sonra bu değişkenlerden birini diğerine atayamam.p
f