Apakah mungkin untuk membuat variabel, dan memberikan sebaris kode padanya, seperti:
ButtonClicked = (MessageBox.Show("Hello, World!"));
... jadi ketika saya menggunakan variabel, itu akan mengeksekusi baris kode.
Apakah mungkin untuk membuat variabel, dan memberikan sebaris kode padanya, seperti:
ButtonClicked = (MessageBox.Show("Hello, World!"));
... jadi ketika saya menggunakan variabel, itu akan mengeksekusi baris kode.
Jawaban:
Anda dapat menetapkannya Actionseperti ini:
var ButtonClicked = new Action(() => MessageBox.Show("hi"));
Kemudian sebut saja:
ButtonClicked();
Untuk kelengkapan (sehubungan dengan berbagai komentar) ...
Seperti yang dikatakan Erik, Anda dapat mengeksekusi beberapa baris kode:
var ButtonClicked = new Action(() =>
{
MessageBox.Show("hi");
MessageBox.Show("something else"); // something more useful than another popup ;)
});
Seperti yang dikatakan Tim, Anda dapat menghilangkan Actionkata kunci tersebut
Action ButtonClicked = () => MessageBox.Show("hi");
Action ButtonClicked = () =>
{
// multiple lines of code
};
Untuk mengatasi komentar KRyan, mengenai tanda kurung kosong, yang mewakili daftar parameter yang ingin Anda kirimkan ke Action (dalam hal ini, tidak ada) .
Jika, misalnya, Anda ingin menentukan pesan ke acara, Anda bisa menambahkan "pesan" sebagai parameter (catatan bahwa saya berubah Action untuk untuk menentukan parameter string tunggal) :Action<string>
Action<string> ButtonClicked = (message) => MessageBox.Show(message);
ButtonClicked("hello world!");
Action ButtonClicked = () => MessageBox.Show("hi");setara dan IMO lebih baik (tambahkan parens jika Anda suka)
WinForms?
Button.Clickacara, dan tidak menyimpannya dalam variabel yang kebetulan dia beri nama ButtonClicked.
Dalam kasus Anda, Anda ingin menggunakan file delegate.
Mari kita lihat bagaimana seorang delegasi bekerja dan bagaimana kita bisa mendapatkan formulir yang lebih mudah dengan memahami konsepnya:
// Create a normal function
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();
Anda lihat, delegasi mengambil bentuk fungsi normal tetapi tanpa argumen apa pun (Ini bisa menggunakan sejumlah argumen seperti metode lain, tetapi demi kesederhanaan, tidak).
Sekarang, mari gunakan apa yang kita miliki; kita akan mendefinisikan delegasi seperti kita mendefinisikan variabel lainnya:
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
Kami pada dasarnya membuat variabel baru bernama ButtonClicked, yang memiliki jenis ButtonClick (yang merupakan delegasi) dan ketika digunakan, akan mengeksekusi metode dalam metode OnButtonClick ().
Untuk menggunakannya kita cukup memanggil:ButtonClicked();
Jadi keseluruhan kodenya adalah:
delegate void ButtonClick();
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
void Foo()
{
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
ButtonClicked(); // Execute the function.
}
Dari sini, kita dapat beralih ke ekspresi lambda dan melihat bagaimana mereka dapat berguna dalam situasi Anda:
Ada banyak delegasi yang sudah ditentukan oleh pustaka .NET, dengan beberapa seperti Action, yang tidak menerima parameter apa pun dan tidak mengembalikan nilai. Ini didefinisikan sebagai public delegate void Action();
Anda selalu dapat menggunakannya untuk kebutuhan Anda alih-alih kebutuhan untuk menentukan delegasi baru setiap saat. Dalam konteks sebelumnya misalnya, Anda bisa saja baru saja menulis
Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();
yang akan melakukan hal yang sama.
Sekarang Anda telah melihat berbagai cara menggunakan delegasi, mari gunakan ekspresi lambda pertama kita. Ekspresi lambda adalah fungsi anonim; jadi, itu adalah fungsi normal tetapi tanpa nama. Mereka adalah dari bentuk-bentuk itu:
x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");
Dalam kasus kami, kami tidak memiliki parameter apa pun jadi kami akan menggunakan ekspresi terakhir. Kita bisa menggunakan ini hanya sebagai fungsi OnButtonClick, tapi kita mendapat keuntungan karena tidak memiliki fungsi bernama. Sebagai gantinya kita bisa melakukan sesuatu seperti ini:
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
atau bahkan lebih mudah,
Action ButtonClicked = () => MessageBox.Show("Hello World!");
maka cukup panggil ButtonClicked();Tentu saja Anda juga dapat memiliki beberapa baris kode, tetapi saya tidak ingin membingungkan Anda lagi. Akan terlihat seperti ini:
Action ButtonClicked = () =>
{
MessageBox.Show("Hello World!");
};
ButtonClicked();
Anda juga bisa bermain-main, misalnya, Anda dapat menjalankan fungsi seperti ini:
new Action(() => MessageBox.Show("Hello World!"))();
Maaf untuk postingan yang panjang, semoga tidak terlalu membingungkan :)
EDIT: Saya lupa menyebutkan bahwa bentuk alternatif yang, meskipun tidak sering digunakan, dapat membuat ekspresi lambda lebih mudah dipahami:
new Action(delegate() {
Console.WriteLine("I am parameterless");
})();
Juga, menggunakan obat generik:
// Defines a delegate that has one parameter of type string. You could pass as many parameters as you want.
new Action<string>(delegate(string x) {
Console.WriteLine(x);
})("I am a string parameter!");
Pada gilirannya, Anda dapat menggunakan ekspresi lambda, tetapi Anda tidak perlu (tetapi mungkin dalam beberapa kasus) untuk menentukan jenis parameter, misalnya, kode di atas dapat dengan mudah ditulis sebagai:
new Action<string>(x => {
Console.WriteLine(x);
})("I am a string parameter!");
atau:
new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");
EDIT2:
Action<string>adalah representasi dari public void delegate Action(string obj);
Action<string,string>adalah representasi public void delegate Action(string obj, string obj2);
Secara umum, Action<T>adalah representasi daripublic void delegate Action<T>(T obj);
EDIT3: Saya tahu posnya sudah ada di sini untuk sementara waktu, tetapi saya pikir ini sangat keren untuk tidak disebutkan: Anda dapat melakukan ini, yang sebagian besar terkait dengan pertanyaan Anda:
dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");
atau sederhana:
Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");
The Lazykelas khusus dirancang untuk mewakili nilai yang tidak akan dihitung sampai Anda meminta untuk itu. Anda membangunnya dengan menyediakan metode yang menentukan bagaimana itu harus dibangun, tetapi itu akan menangani eksekusi metode itu tidak lebih dari sekali (bahkan saat menghadapi beberapa utas yang meminta nilai) dan hanya mengembalikan nilai yang sudah dibangun untuk permintaan tambahan apa pun:
var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));
var result = foo.Value;
Lazyharus digunakan untuk nilai yang membutuhkan banyak daya pemrosesan, dan Anda tidak boleh menggunakannya untuk interaksi (karena semantiknya .Valueadalah ia mengembalikan nilai, mirip dengan properti, bukan tindakan (interaktif)). Sebagai gantinya, seorang delegasi harus digunakan untuk tindakan semacam itu.
Value yang digunakan; itu DialogResultditerima dari menampilkan kotak pesan. Perbedaan utama antara solusi ini dan penggunaan delegasi adalah apakah nilai harus dihitung ulang setiap kali diminta atau tidak. Interpretasi saya tentang persyaratan adalah bahwa ini secara konseptual menginisialisasi nilai, bukan operasi yang akan diulang.
Lazydapat dengan mudah digunakan secara salah. Ini memiliki overhead sendiri, menggunakannya "hanya" untuk menunda tugas kecil akan meminta lebih banyak overhead daripada keuntungannya. Menampilkan kotak pesan dari suatu properti adalah (imo) praktik buruk secara umum, terlepas dari Lazy. Btw, dari MSDN, saya mengutip: "Gunakan inisialisasi malas untuk menunda pembuatan objek yang besar atau intensif sumber daya" . Anda bisa saja tidak setuju dengan itu, tapi itu memang awalnya dirancang untuk itu.
Lazykonteks seperti ini tentunya dapat diabaikan; itu akan sepi dibandingkan dengan waktu yang dihabiskan menunggu manusia untuk mengklik kotak pesan. Ini sebagian besar bermuara pada persyaratan nyata dari aplikasi yang mendasarinya; ketidakjelasan pertanyaan membuat jawaban yang benar secara objektif menjadi tidak mungkin. Ini adalah salah satu interpretasi dari pertanyaan tersebut. Adapun melakukan banyak pekerjaan di properti getter menjadi buruk; tampaknya Anda pada dasarnya menentang keseluruhan desain Lazy. Terima kasih atas opini itu.
MessageBox overhead dapat diabaikan (saya tidak akan menggunakan UI di dalam properti). Maksud saya tugas-tugas kecil secara umum (seperti menunda 2 + 3 * 4 / i), di mana biaya pembuatan penutupan lebih besar daripada perhitungan itu sendiri. Dan saya pikir saya sepenuhnya merangkul Lazy, pada kenyataannya kami banyak menggunakannya di F # (sedikit lebih sedikit di C #) dan kami telah belajar dengan cara yang sulit bahwa Anda harus berhati-hati dengannya, khususnya. sehubungan dengan kinerja.
Cara saya membaca pertanyaan Anda, apakah ini dalam konteks kontrol GUI?
Jika ini ada di WPF, lihat cara yang "benar" untuk menangani perintah dari kontrol: http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx
... tapi itu bisa menjadi sakit dan berlebihan. Untuk kasus umum yang lebih sederhana, Anda mungkin mencari pengendali event, seperti:
myButton.Click += (o, e) => MessageBox.Show("Hello, World!");
Penangan kejadian itu dapat ditangani dengan berbagai cara. Contoh di atas menggunakan fungsi anonim, tetapi Anda juga dapat melakukan:
Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World");
myButton.Click += new RoutedEventHandler(sayHello);
... seperti yang Anda tanyakan, dengan fungsi (atau di sini, "Action", karena mengembalikan void) yang ditetapkan sebagai variabel.
Anda dapat menetapkan kode C # ke variabel, mengkompilasinya saat runtime dan menjalankan kode:
Tulis kode Anda:
// Assign C# code to the code variable.
string code = @"
using System;
namespace First
{
public class Program
{
public static void Main()
{
" +
"Console.WriteLine(\"Hello, world!\");"
+ @"
}
}
}
";Buat penyedia dan parameter kompilator:
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();Tentukan parameter kompilator:
// Reference to System.Drawing library
parameters.ReferencedAssemblies.Add("System.Drawing.dll");
// True - memory generation, false - external file generation
parameters.GenerateInMemory = true;
// True - exe file generation, false - dll file generation
parameters.GenerateExecutable = true;Kompilasi perakitan:
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);Periksa kesalahan:
if (results.Errors.HasErrors)
{
StringBuilder sb = new StringBuilder();
foreach (CompilerError error in results.Errors)
{
sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
}
throw new InvalidOperationException(sb.ToString());
}Dapatkan perakitan, jenis dan metode Utama:
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("First.Program");
MethodInfo main = program.GetMethod("Main");Menjalankannya:
main.Invoke(null, null);Referensi:
http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime