Ini hanya jalan pintas untuk delegasi dengan tanda tangan tertentu. Untuk memahami sepenuhnya jawaban di bawah, Anda harus memahami para delegasi ;-)
Theo Lenndorff
2
Dalam jawaban dari @Oded dikatakanIf you have a function that needs to return different types, depending on the parameters, you can use a Func delegate, specifying the return type.
LCJ
Jawaban:
76
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
Tapi itu juga bisa mewakili fungsi satu argumen statis =)
Ark-kun
2
@ Ark-kun tidak, itu tidak benar. Definisi dari Func<T>adalah delegate TResult Func<out TResult>(). Tidak ada argumen. Func<T1, T2>akan menjadi fungsi yang membutuhkan satu argumen.
Brian Rasmussen
4
Tidak, saya benar. static int OneArgFunc(this string i) { return 42; }Func<int> f = "foo".OneArgFunc;. =)
Ark-kun
1
Itu adalah metode penyuluhan yang istimewa.
Brian Rasmussen
Satu-satunya hal khusus tentang itu adalah Extensionatribut 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.
Ark-kun
87
Anggap saja sebagai placeholder. Ini bisa sangat berguna ketika Anda memiliki kode yang mengikuti pola tertentu tetapi tidak perlu terikat pada fungsi tertentu.
The Pola adalah: untuk setiap item secara berurutan, pilih beberapa nilai dari item yang (misalnya, properti) dan membuat urutan baru yang terdiri dari nilai-nilai ini.
The placeholder adalah: beberapa fungsi pemilih yang benar-benar mendapat nilai-nilai untuk urutan yang dijelaskan di atas.
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.Namedanp => p.Age ).
Alternatifnya adalah menulis versi berbeda Selectsetiap 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.
Kemudian Anda harus membuat kelas PrintListToConsole<T>yang mengambil antarmuka yang dibuat sebelumnya dan menggunakannya di setiap elemen daftar.
classPrintListToConsole<T>{privatePrintListConsoleRender<T> _renderer;publicvoidSetRenderer(PrintListConsoleRender<T> r){// this is the point where I can personalize the render mechanism
_renderer = r;}publicvoidPrintToConsole(List<T>list){foreach(var item inlist){Console.Write(_renderer.Render(item));}}}
Pengembang yang perlu menggunakan komponen Anda harus:
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)
classPrintListToConsole<T>{privateFunc<T,String> _renderFunc;publicvoidSetRenderFunc(Func<T,String> r){// this is the point where I can set the render mechanism
_renderFunc = r;}publicvoidPrint(List<T>list){foreach(var item inlist){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.
classProgram{staticvoidMain(string[] args){varlist=newList<int>{1,2,3};// should be a list as the method signature expectsvar printer =newPrintListToConsole<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.
Terima kasih telah memposting Marco ini. Itu sangat membantu saya. Saya telah mencoba untuk memahami func untuk sementara waktu dan juga secara aktif menggunakannya dalam pemrograman saya. Contoh ini akan menghapus jalur. Saya harus menambahkan metode StampaFunc seperti yang ditinggalkan dalam kode asli yang mencegahnya untuk ditampilkan.
Siwoku Adeola
1
Saya rasa ada baris yang terlewat dalam sampel Func, Di mana panggilan untuk fungsi cetak atau StampaFunc?
Bashar Abu Shamaa
11
Func<T1,R>dan Funcdelegasi 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 Funcdelegasi, 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.
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 tipeT
.Dengan kata lain, Anda bisa menggunakan tipe ini untuk mereferensikan metode yang mengembalikan beberapa nilai
T
. Misalnyamungkin direferensikan seperti ini
sumber
Func<T>
adalahdelegate 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:Atau katakan saya ingin usia setiap orang:
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:Dengan seorang delegasi bertindak sebagai placeholder, saya membebaskan diri saya dari keharusan menulis pola yang sama berulang kali dalam kasus seperti ini.
sumber
Func<T1, T2, ..., Tn, Tr>
mewakili sebuah fungsi, yang mengambil argumen (T1, T2, ..., Tn) dan mengembalikan Tr.Misalnya, jika Anda memiliki fungsi:
Anda bisa menyimpannya sebagai semacam variabel fungsi:
Dan kemudian gunakan persis seperti yang Anda gunakan sqr:
dll.
Ingat juga, itu adalah delegasi, untuk info lebih lanjut lihat dokumentasi.
sumber
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.
Kemudian Anda harus membuat kelas
PrintListToConsole<T>
yang mengambil antarmuka yang dibuat sebelumnya dan menggunakannya di setiap elemen daftar.Pengembang yang perlu menggunakan komponen Anda harus:
menerapkan antarmuka
meneruskan kelas nyata ke
PrintListToConsole
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)Ketika pengembang menggunakan komponen Anda, dia cukup meneruskan implementasi
Func<T, String>
tipe ke komponen , yaitu fungsi yang membuat keluaran untuk konsol.Func<T>
memungkinkan Anda menentukan antarmuka metode umum dengan cepat. Anda menentukan jenis masukan dan jenis keluarannya. Sederhana dan ringkas.sumber
Func<T1,R>
danFunc
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.sumber
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.sumber
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:
Definisi:
Dimana itu digunakan:
Ini digunakan dalam ekspresi lambda dan metode anonim.
sumber