Untuk apa Func<>
dan digunakan untuk apa?
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.
Untuk apa Func<>
dan digunakan untuk apa?
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.
Jawaban:
Func<T>
adalah tipe delegasi yang telah ditentukan sebelumnya untuk metode yang mengembalikan beberapa nilai tipe T
.
Dengan kata lain, Anda bisa menggunakan tipe ini untuk mereferensikan metode yang mengembalikan beberapa nilai T
. Misalnya
public static string GetMessage() { return "Hello world"; }
mungkin direferensikan seperti ini
Func<string> f = GetMessage;
Func<T>
adalah delegate TResult Func<out TResult>()
. Tidak ada argumen. Func<T1, T2>
akan menjadi fungsi yang membutuhkan satu argumen.
static int OneArgFunc(this string i) { return 42; }
Func<int> f = "foo".OneArgFunc;
. =)
Extension
atribut yang hanya dibaca oleh kompiler C # / VB.Net, bukan CLR. Pada dasarnya, metode instance (tidak seperti fungsi statis) memiliki parameter "ini" ke-0 yang tersembunyi. Jadi, metode instance 1-argumen sangat mirip dengan fungsi statis 2-argumen. Kemudian, kami memiliki delegasi yang menyimpan objek target dan penunjuk fungsi . Delegasi dapat menyimpan argumen pertama dalam target atau tidak melakukan itu.
Anggap saja sebagai placeholder. Ini bisa sangat berguna ketika Anda memiliki kode yang mengikuti pola tertentu tetapi tidak perlu terikat pada fungsi tertentu.
Misalnya, pertimbangkan Enumerable.Select
metode ekstensi.
Metode ini mengambil Func<T, TResult>
alih fungsi konkret. Ini memungkinkannya untuk digunakan dalam konteks apa pun di mana pola di atas berlaku.
Jadi misalnya, katakan saya punya a List<Person>
dan saya hanya ingin nama setiap orang yang ada di daftar. Aku bisa melakukan ini:
var names = people.Select(p => p.Name);
Atau katakan saya ingin usia setiap orang:
var ages = people.Select(p => p.Age);
Langsung saja, Anda dapat melihat bagaimana saya dapat memanfaatkan kode yang sama yang mewakili pola (dengan Select
) dengan dua perbedaan fungsi ( p => p.Name
danp => p.Age
).
Alternatifnya adalah menulis versi berbeda Select
setiap kali Anda ingin memindai urutan untuk jenis nilai yang berbeda. Jadi untuk mencapai efek yang sama seperti di atas, saya membutuhkan:
// 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);
Dengan seorang delegasi bertindak sebagai placeholder, saya membebaskan diri saya dari keharusan menulis pola yang sama berulang kali dalam kasus seperti ini.
Func<T1, T2, ..., Tn, Tr>
mewakili sebuah fungsi, yang mengambil argumen (T1, T2, ..., Tn) dan mengembalikan Tr.
Misalnya, jika Anda memiliki fungsi:
double sqr(double x) { return x * x; }
Anda bisa menyimpannya sebagai semacam variabel fungsi:
Func<double, double> f1 = sqr;
Func<double, double> f2 = x => x * x;
Dan kemudian gunakan persis seperti yang Anda gunakan sqr:
f1(2);
Console.WriteLine(f2(f1(4)));
dll.
Ingat juga, itu adalah delegasi, untuk info lebih lanjut lihat dokumentasi.
Saya merasa Func<T>
sangat berguna ketika saya membuat komponen yang perlu dipersonalisasi "dengan cepat".
Ambil contoh yang sangat sederhana ini: sebuah PrintListToConsole<T>
komponen.
Objek yang sangat sederhana yang mencetak daftar objek ini ke konsol. Anda ingin mengizinkan pengembang yang menggunakannya mempersonalisasi keluaran.
Misalnya, Anda ingin membiarkan dia menentukan jenis format angka tertentu dan seterusnya.
Tanpa Func
Pertama, Anda harus membuat antarmuka untuk kelas yang menerima input dan menghasilkan string untuk dicetak ke konsol.
interface PrintListConsoleRender<T> {
String Render(T input);
}
Kemudian Anda harus membuat kelas PrintListToConsole<T>
yang mengambil antarmuka yang dibuat sebelumnya dan menggunakannya di setiap elemen daftar.
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));
}
}
}
Pengembang yang perlu menggunakan komponen Anda harus:
menerapkan antarmuka
meneruskan kelas nyata ke 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();
}
}
Menggunakan Func jauh lebih sederhana
Di dalam komponen Anda menentukan parameter tipe Func<T,String>
yang mewakili antarmuka fungsi yang mengambil parameter input tipe T dan mengembalikan string (output untuk konsol)
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));
}
}
}
Ketika pengembang menggunakan komponen Anda, dia cukup meneruskan implementasi Func<T, String>
tipe ke komponen , yaitu fungsi yang membuat keluaran untuk konsol.
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>
memungkinkan Anda menentukan antarmuka metode umum dengan cepat.
Anda menentukan jenis masukan dan jenis keluarannya. Sederhana dan ringkas.
Func<T1,R>
dan Func
delegasi generik standar lainnya ( Func<T1,T2,R>
, Func<T1,T2,T3,R>
dan lainnya) adalah delegasi generik yang mengembalikan tipe parameter generik terakhir.
Jika Anda memiliki fungsi yang perlu mengembalikan tipe berbeda, bergantung pada parameternya, Anda bisa menggunakan Func
delegasi, menentukan tipe kembalian.
Ini hanyalah delegasi umum yang telah ditentukan sebelumnya. Dengan menggunakannya, Anda tidak perlu mendeklarasikan setiap delegasi. Ada delegasi lain yang ditentukan sebelumnya Action<T, T2...>
, yang sama tetapi mengembalikan kosong.
Mungkin belum terlambat untuk menambahkan beberapa info.
Jumlah:
Func adalah delegasi khusus yang ditentukan dalam namespace Sistem yang memungkinkan Anda untuk menunjuk ke metode dengan tanda tangan yang sama (seperti yang dilakukan delegasi), menggunakan 0 hingga 16 parameter input dan itu harus mengembalikan sesuatu.
Nomenklatur & how2use:
Func<input_1, input_2, ..., input1_6, output> funcDelegate = someMethod;
Definisi:
public delegate TResult Func<in T, out TResult>(T arg);
Dimana itu digunakan:
Ini digunakan dalam ekspresi lambda dan metode anonim.