Kita semua tahu bahwa properti di C # dikompilasi dengan metode lama sebenarnya. Tetapi tidak seperti metode (-group), mereka tidak dapat diberikan sebagai argumen untuk metode lain yang mengharapkan delegasi seperti Func<T>
atau Action<T>
(pengambil dan penyetel). Apakah ada sesuatu yang khusus melarang ini, atau itu hanya fitur yang tidak datang "secara gratis" ketika membuat grup metode secara implisit dapat dikonversi menjadi delegasi?
Kode contoh:
public class MyClass
{
public static int X { get; set; }
}
private static void Foo<T>(Func<T> f)
{
Console.WriteLine(f());
}
private static void Bar<T>(Action<T> f)
{
f(default(T));
}
private static void Test()
{
// neither of these lines compile, even with an explicit type-cast.
Foo(MyClass.X);
Bar(MyClass.X);
}
Jika saya harus menebak, saya akan mengatakan bahwa masalah sintaksis yang membedakan antara pemanggilan dan referensi ke properti itu sendiri tidak layak untuk diselesaikan ketika kita bisa melakukan sedikit saja penulisan () => MyClass.X
atau x => MyClass.X = x
.
c#
properties
delegates
sara
sumber
sumber
set
adalahAction
danget
merupakanFunc
misalnyadelegate {return SomeProperty}
melewati pengambil;delegate(YourType value) {SomeProperty = value}
melewati setter. Jika Anda hanya perlu melewati satu atau dua tempat, ini adalah singkatan untuk metode terbungkus yang seharusnya Anda buat.Interface
dengan properti itu, dan mengubah tanda tangan dari metode yang disebut untuk mengambil bahwa antarmuka sebagai parameter.Jawaban:
Masalahnya adalah "MyClass.X" memiliki makna yang jelas, yaitu memanggil pengambil pada properti "X". Yang penting untuk dicatat adalah bahwa, meskipun suatu metode sedang dipanggil, tanda kurung tidak diperlukan.
Di sisi lain, saat memanggil metode biasa, seperti ketika Anda menelepon "Foo" dalam kode contoh Anda, tanda kurung yang diperlukan untuk menunjukkan bahwa metode harus dieksekusi. Jika Anda ingin memberikan referensi ke suatu metode maka Anda akan mengecualikan tanda kurung (lihat contoh di bawah).
Ini berarti bahwa tidak ada ambiguitas ketika mereferensikan suatu metode - baik Anda mengeksekusinya segera (melewati argumen apa pun yang diperlukan dan termasuk tanda kurung) atau Anda meneruskan metode tersebut sebagai argumen (tanpa tanda kurung).
Dengan pengambil properti atau penyetel, tidak ada tanda kurung berarti "segera jalankan pengambil / penyetel". Jika pengambil properti / penyetel juga bisa diteruskan sebagai grup metode maka terkadang "x.Name" akan berarti "jalankan pengambil Nama sekarang" dan kadang-kadang itu berarti "lulus pengambil Nama sebagai grup metode". Meskipun dimungkinkan untuk mengubah kompiler menjadi disambiguasi berdasarkan apakah "x.Name" tampaknya diteruskan ke fungsi yang mengharapkan string (dalam hal ini pengambil akan dieksekusi) atau apakah tampaknya akan masuk ke dalam fungsi yang mengharapkan Func <string> (dalam hal ini pengambil akan disahkan sebagai grup metode), tim bahasa C # mencoba untuk menghindari skenario yang berpotensi membingungkan ini.
sumber
Itu tidak mungkin karena dasar-dasar bagaimana tata bahasa dan kompiler bekerja.
Ekspresi dievaluasi "bottom up", yang berarti ekspresi
MyClass.X
mengevaluasi nilai int sebelum hasil ini dimasukkan sebagai argumen fungsi. Proposal Anda tampaknya menyarankan bahwa konteks - jenis parameter - dapat mengarahkan jika ekspresi harus ditafsirkan sebagai permohonan pengambil atau sebagai penyempurnaan terhadap metode pengambil itu sendiri. Ini tidak mungkin dilakukan dengan cara yang tidak ambigu. Bagaimana jika jenis properti itu sendiri adalah aFunc
atauAction
? Dan bagaimana akanvar x = MyClass.X
ditafsirkan? Bagaimana jika metode ini memiliki overloads dengan baikint
atauFunc
atauAction
parameter?Untuk menyelesaikan ambiguitas ini, Anda memerlukan perbedaan di tingkat sintaksis, mis. Operator dengan dukungan khusus dalam tata bahasa seperti
typeof
operator, mis:Tapi ini akan jauh merepotkan untuk fitur dengan manfaat terbatas.
sumber
Foo.Do()
artinya doa danFoo.Do
menjadi, delegasi baik-baik saja.Foo.X
menjadi properti serta delegasi pengambil dan delegasi pengambil tergantung pada perbedaan konteks yang halus membingungkan. Fitur bagus yang tidak terlalu bagus bahkan tidak masuk ke C #, ini sepertinya yang buruk. Jika Anda ingin menulis singkat setelah kode coba Perl.Sudah ada cara untuk menyatakan dengan jelas mana yang Anda butuhkan di C #, saya tidak melihat masalah.
sumber