Ne Func<>
için kullanılır ve ne için kullanılır?
If you have a function that needs to return different types, depending on the parameters, you can use a Func delegate, specifying the return type.
Ne Func<>
için kullanılır ve ne için kullanılır?
If you have a function that needs to return different types, depending on the parameters, you can use a Func delegate, specifying the return type.
Yanıtlar:
Func<T>
türün bir değerini döndüren bir yöntem için önceden tanımlanmış bir temsilci türüdür T
.
Başka bir deyişle, bu türü bir değer döndüren bir yönteme başvurmak için kullanabilirsiniz T
. Örneğin
public static string GetMessage() { return "Hello world"; }
bu şekilde referans verilebilir
Func<string> f = GetMessage;
Func<T>
IS delegate TResult Func<out TResult>()
. Tartışma yok. Func<T1, T2>
bir argüman alan bir işlev olacaktır.
static int OneArgFunc(this string i) { return 42; }
Func<int> f = "foo".OneArgFunc;
. =)
Extension
, CLR değil, yalnızca C # / VB.Net derleyicileri tarafından okunan özniteliktir. Temel olarak, örnek yöntemlerin (statik işlevlerin aksine) gizli bir 0'ıncı "this" parametresi vardır. Dolayısıyla, 1 bağımsız değişkenli örnek yöntemi 2 bağımsız değişkenli statik işleve çok benzer. Ardından, hedef nesneyi ve işlev işaretçisini depolayan delegelerimiz var . Temsilciler ilk argümanı hedefte saklayabilir veya yapmayabilir .
Yer tutucu olarak düşünün. Belirli bir modeli izleyen ancak herhangi bir özel işleve bağlı olması gerekmeyen bir kodunuz olduğunda oldukça yararlı olabilir.
Örneğin, Enumerable.Select
uzantı yöntemini düşünün .
Bu yöntem Func<T, TResult>
, herhangi bir somut işlev yerine a alır . Bu, herhangi bir , yukarıdaki modelin geçerli olduğu bağlamda .
Örneğin, bir diyelim ki List<Person>
listedeki her kişinin adını istiyorum. Bunu yapabilirim:
var names = people.Select(p => p.Name);
Ya da her insanın yaşını istediğimi söyle :
var ages = people.Select(p => p.Age);
Hemen, iki farklı işleve sahip bir modeli (ve ) temsil eden aynı kodu nasıl kullanabildiğimi görebilirsiniz ( veSelect
p => p.Name
p => p.Age
) .
Alternatif, farklı Select
bir değer türü için bir dizi taramak istediğiniz her seferin farklı bir versiyonunu yazmaktır . Dolayısıyla, yukarıdakiyle aynı etkiyi elde etmek için şunlara ihtiyacım var:
// Presumably, the code inside these two methods would look almost identical;
// the only difference would be the part that actually selects a value
// based on a Person.
var names = GetPersonNames(people);
var ages = GetPersonAges(people);
Yer tutucu olarak hareket eden bir delege ile bu tür durumlarda aynı kalıbı defalarca yazmaktan kendimi kurtarıyorum.
Func<T1, T2, ..., Tn, Tr>
(T1, T2, ..., Tn) bağımsız değişkenleri alan ve Tr döndüren bir işlevi temsil eder.
Örneğin, bir işleviniz varsa:
double sqr(double x) { return x * x; }
Bunu bir tür işlev değişkeni olarak kaydedebilirsiniz:
Func<double, double> f1 = sqr;
Func<double, double> f2 = x => x * x;
Ve sonra tam olarak sqr kullanacağınız gibi kullanın:
f1(2);
Console.WriteLine(f2(f1(4)));
vb.
Yine de bunun bir temsilci olduğunu unutmayın, daha gelişmiş bilgiler için belgelere bakın.
Func<T>
"Anında" kişiselleştirilmesi gereken bir bileşen oluşturduğumda çok faydalı buluyorum .
Şu çok basit örneği ele alalım: bir PrintListToConsole<T>
bileşen.
Bu nesne listesini konsola yazdıran çok basit bir nesne. Onu kullanan geliştiricinin çıktıyı kişiselleştirmesine izin vermek istiyorsunuz.
Örneğin, belirli bir sayı biçimi türünü tanımlamasına izin vermek istiyorsunuz vb.
Func olmadan
İlk olarak, girdiyi alan ve konsola yazdırmak üzere dizeyi üreten bir sınıf için bir arabirim oluşturmanız gerekir.
interface PrintListConsoleRender<T> {
String Render(T input);
}
Daha sonra PrintListToConsole<T>
, önceden oluşturulmuş arayüzü alan ve onu listenin her bir öğesi üzerinde kullanan sınıfı oluşturmanız gerekir .
class PrintListToConsole<T> {
private PrintListConsoleRender<T> _renderer;
public void SetRenderer(PrintListConsoleRender<T> r) {
// this is the point where I can personalize the render mechanism
_renderer = r;
}
public void PrintToConsole(List<T> list) {
foreach (var item in list) {
Console.Write(_renderer.Render(item));
}
}
}
Bileşeninizi kullanması gereken geliştiricinin şunları yapması gerekir:
arayüzü uygula
gerçek sınıfı geçmek PrintListToConsole
class MyRenderer : PrintListConsoleRender<int> {
public String Render(int input) {
return "Number: " + input;
}
}
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 };
var printer = new PrintListToConsole<int>();
printer.SetRenderer(new MyRenderer());
printer.PrintToConsole(list);
string result = Console.ReadLine();
}
}
Func'u kullanmak çok daha basit
Bileşen İçerisinde tipte bir parametreyi bir fonksiyonun bir ara birim olan bir dizi (konsol için çıkış) T türü bir giriş parametresi alır ve dönerFunc<T,String>
class PrintListToConsole<T> {
private Func<T, String> _renderFunc;
public void SetRenderFunc(Func<T, String> r) {
// this is the point where I can set the render mechanism
_renderFunc = r;
}
public void Print(List<T> list) {
foreach (var item in list) {
Console.Write(_renderFunc(item));
}
}
}
Geliştirici bileşeninizi kullandığında, bileşene Func<T, String>
, konsolun çıktısını oluşturan bir işlev olan türün uygulamasını basitçe aktarır .
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 }; // should be a list as the method signature expects
var printer = new PrintListToConsole<int>();
printer.SetRenderFunc((o) => "Number:" + o);
printer.Print(list);
string result = Console.ReadLine();
}
}
Func<T>
anında genel bir yöntem arabirimi tanımlamanıza izin verir.
Girdinin ne tür olduğunu ve çıktının ne tür olduğunu tanımlarsınız. Basit ve öz.
Func<T1,R>
ve diğer önceden tanımlanmış jenerik Func
delegeler ( Func<T1,T2,R>
, Func<T1,T2,T3,R>
ve diğerleri) son jenerik parametrenin türünü döndürür jenerik delegeler bulunmaktadır.
Parametrelere bağlı olarak farklı türler döndürmesi gereken bir işleviniz varsa Func
, dönüş türünü belirten bir temsilci kullanabilirsiniz .
Bu sadece önceden tanımlanmış genel bir temsilcidir. Bunu kullanarak her delegeyi bildirmenize gerek yoktur. Önceden tanımlanmış başka bir delege daha Action<T, T2...>
vardır, bu aynıdır ancak void döndürür.
Belki biraz bilgi eklemek için çok geç değil.
Toplam:
Func, 0 ila 16 giriş parametresi kullanarak aynı imzaya sahip bir yöntemi (temsilcilerin yaptığı gibi) işaret etmenize olanak tanıyan ve bir şey döndürmesi gereken Sistem ad alanında tanımlanan özel bir temsilcidir.
İsimlendirme ve nasıl kullanılır:
Func<input_1, input_2, ..., input1_6, output> funcDelegate = someMethod;
Tanım:
public delegate TResult Func<in T, out TResult>(T arg);
Nerede kullanılır:
Lambda ifadelerinde ve anonim yöntemlerde kullanılır.