Saya memiliki kode berikut:
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
Namun, yang berikut ini tidak dikompilasi:
var comparer = delegate(string value) {
return value != "0";
};
Mengapa kompiler tidak mengetahui bahwa itu adalah Func<string, bool>
? Dibutuhkan satu parameter string, dan mengembalikan boolean. Sebaliknya, itu memberi saya kesalahan:
Tidak dapat menetapkan metode anonim ke variabel lokal yang diketik secara implisit.
Saya punya satu tebakan dan itu adalah jika versi var dikompilasi , itu akan kurang konsisten jika saya memiliki yang berikut:
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
Hal di atas tidak masuk akal karena Func <> hanya memungkinkan hingga 4 argumen (dalam. NET 3.5, yang saya gunakan). Mungkin seseorang bisa mengklarifikasi masalahnya. Terima kasih.
Func<>
menerima hingga 16 argumen.Func<string, bool>
? SepertinyaConverter<string, bool>
bagi saya!Dim comparer = Function(value$) value <> "0"
Jawaban:
Yang lain telah menunjukkan bahwa ada banyak kemungkinan tipe delegasi yang dapat Anda maksudkan; apa yang begitu istimewa tentang
Func
hal itu yang layak dijadikan standar alih-alihPredicate
atauAction
atau segala kemungkinan lain? Dan, untuk lambdas, mengapa jelas bahwa tujuannya adalah untuk memilih bentuk delegasi, daripada bentuk pohon ekspresi?Tetapi kita dapat mengatakan bahwa
Func
itu istimewa, dan bahwa jenis lambda atau metode anonim yang disimpulkan adalah Fungsi dari sesuatu. Kami masih memiliki semua jenis masalah. Jenis apa yang ingin Anda simpulkan untuk kasus-kasus berikut?Tidak ada
Func<T>
tipe yang membutuhkan referensi apa pun.Kami tidak tahu jenis parameter formal, meskipun kami tahu pengembaliannya. (Atau apakah kita? Apakah return int? Long? Short? Byte?)
Kami tidak tahu tipe pengembalian, tetapi tidak bisa dibatalkan. Jenis pengembalian dapat berupa jenis referensi atau jenis nilai yang dapat dibatalkan.
Sekali lagi, kita tidak tahu tipe pengembalian, dan kali ini bisa batal.
Apakah itu dimaksudkan sebagai pernyataan lambda yang batal atau sesuatu yang mengembalikan nilai yang ditugaskan ke q? Keduanya legal; mana yang harus kita pilih?
Sekarang, Anda mungkin berkata, yah, hanya saja tidak mendukung semua fitur itu. Hanya mendukung kasus "normal" di mana jenis dapat dikerjakan. Itu tidak membantu. Bagaimana hal itu membuat hidup saya lebih mudah? Jika fitur ini bekerja kadang-kadang dan kadang-kadang gagal maka saya masih harus menulis kode untuk mendeteksi semua situasi kegagalan itu dan memberikan pesan kesalahan yang berarti untuk masing-masing. Kami masih harus menentukan semua perilaku itu, mendokumentasikannya, menulis tes untuk itu, dan sebagainya. Ini adalah fitur yang sangat mahal yang menghemat pengguna mungkin setengah lusin penekanan tombol. Kami memiliki cara yang lebih baik untuk menambahkan nilai pada bahasa daripada menghabiskan banyak waktu untuk menulis kasus uji untuk fitur yang tidak berfungsi separuh waktu dan tidak memberikan manfaat apa pun dalam kasus di mana ia berfungsi.
Situasi di mana itu sebenarnya berguna adalah:
karena tidak ada tipe yang "bisa bicara" untuk hal itu. Tapi kami memiliki masalah ini sepanjang waktu, dan kami hanya menggunakan inferensi tipe metode untuk menyimpulkan tipe:
dan sekarang inferensi tipe metode berhasil apa tipe func.
sumber
Hanya Eric Lippert yang tahu pasti, tapi saya pikir itu karena tanda tangan dari tipe delegasi tidak secara unik menentukan tipe.
Pertimbangkan contoh Anda:
Berikut adalah dua kemungkinan kesimpulan untuk apa yang
var
seharusnya:Yang mana yang harus disimpulkan oleh kompiler? Tidak ada alasan yang baik untuk memilih satu atau yang lain. Dan meskipun secara
Predicate<T>
fungsional setara dengan aFunc<T, bool>
, mereka masih tipe yang berbeda pada tingkat sistem tipe .NET. Kompiler karena itu tidak dapat secara jelas menyelesaikan tipe delegasi, dan harus gagal inferensi tipe.sumber
Eric Lippert memiliki posting lama tentang itu di mana katanya
sumber
Delegasi yang berbeda dianggap tipe yang berbeda. misalnya,
Action
berbeda dariMethodInvoker
, dan sebuah instance dariAction
tidak dapat ditugaskan ke variabel tipeMethodInvoker
.Jadi, diberikan delegasi anonim (atau lambda) seperti
() => {}
, apakah itu sebuahAction
atauMethodInvoker
? Kompilator tidak tahu.Demikian pula, jika saya menyatakan tipe delegasi mengambil
string
argumen dan mengembalikan argumenbool
, bagaimana kompiler tahu Anda benar-benar menginginkanFunc<string, bool>
tipe delegasi saya? Itu tidak dapat menyimpulkan tipe delegasi.sumber
Poin-poin berikut berasal dari MSDN tentang Variabel Lokal yang Diketik Secara Implisit:
Referensi MSDN: Variabel Lokal yang Diketik Secara Implisit
Mempertimbangkan hal-hal berikut tentang Metode Anonim:
Referensi MSDN: Metode Anonim
Saya menduga bahwa karena metode anonim sebenarnya memiliki tanda tangan metode yang berbeda, kompiler tidak dapat menyimpulkan dengan tepat apa jenis yang paling tepat untuk ditugaskan.
sumber
Posting saya tidak menjawab pertanyaan aktual, tetapi menjawab pertanyaan mendasar:
"Bagaimana caranya agar aku tidak mengetik seperti itu
Func<string, string, int, CustomInputType, bool, ReturnType>
?" [1]Menjadi programmer malas / hacky seperti saya, saya bereksperimen dengan menggunakan
Func<dynamic, object>
- yang mengambil parameter input tunggal dan mengembalikan objek.Untuk beberapa argumen, Anda dapat menggunakannya seperti:
Tip: Anda dapat menggunakan
Action<dynamic>
jika Anda tidak perlu mengembalikan objek.Ya saya tahu itu mungkin bertentangan dengan prinsip pemrograman Anda, tetapi ini masuk akal bagi saya dan mungkin beberapa coders Python.
Saya cukup pemula di delegasi ... hanya ingin membagikan apa yang saya pelajari.
[1] Ini mengasumsikan bahwa Anda tidak memanggil metode yang memerlukan
Func
parameter yang telah ditentukan sebelumnya , dalam hal ini, Anda harus mengetikkan string yang tidak jelas: /sumber
Bagaimana dengan itu?
sumber