将代码分配给一个variables
是否可以创build一个variables,并为其分配一行代码,例如:
ButtonClicked = (MessageBox.Show("Hello, World!"));
…所以当我使用variables时,它将执行代码行。
你可以把它分配给这样一个Action
:
var ButtonClicked = new Action(() => MessageBox.Show("hi"));
然后调用它:
ButtonClicked();
为了完整性(关于各种意见)…
正如Erik所说,你可以执行多行代码:
var ButtonClicked = new Action(() => { MessageBox.Show("hi"); MessageBox.Show("something else"); // something more useful than another popup ;) });
正如Tim所说,你可以省略Action
关键字
Action ButtonClicked = () => MessageBox.Show("hi"); Action ButtonClicked = () => { // multiple lines of code };
为了解决KRyan的评论,关于空圆括号,它代表你想要发送给Action的参数列表(在这种情况下,没有) 。
例如,如果您想要指定要显示的消息,则可以将“message”添加为参数(请注意,我已将 Action
更改 为 Action<string>
以便指定单个string参数) :
Action<string> ButtonClicked = (message) => MessageBox.Show(message); ButtonClicked("hello world!");
在你的情况下,你想使用一个delegate
。
让我们看看委托人是如何工作的,以及如何通过理解委托人的概念来获得更简单的forms:
// Create a normal function void OnButtonClick() { MessageBox.Show("Hello World!"); } // Now we create a delegate called ButtonClick delegate void ButtonClick();
你看,代表采取正常函数的forms,但没有任何参数(它可以采取任何数量的参数就像任何其他方法,但为了简单起见,它不)。
现在,让我们用我们所拥有的; 我们将定义委托,就像我们定义任何其他variables一样:
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
我们基本上创build了一个名为ButtonClicked的新variables,它有一个ButtonClicktypes(它是一个委托),使用时将在OnButtonClick()方法中执行该方法。
要使用它,我们只需调用: ButtonClicked();
所以整个代码将是:
delegate void ButtonClick(); void OnButtonClick() { MessageBox.Show("Hello World!"); } void Foo() { ButtonClick ButtonClicked = new ButtonClick(OnButtonClick); ButtonClicked(); // Execute the function. }
从这里,我们可以移动到lambdaexpression式,看看它们在你的情况下是如何有用的:
有许多已经由.NET库定义的委托,有些像Action,它们不接受任何参数,也不返回任何值。 它被定义为public delegate void Action();
您可以随时使用它来满足您的需求,而不必每次都定义一个新的委托。 例如,在前面的情况下,你可能已经写了
Action ButtonClicked = new Action(OnButtonClick); ButtonClicked();
这样做也是一样的。
现在您已经看到了如何使用委托的不同方式,我们使用我们的第一个lambdaexpression式。 Lambdaexpression式是匿名函数; 所以,他们是正常的function,但没有名字。 它们是这些forms:
x => DoSomethingWithX(x); (x) => DoSomethingWithX(x); (x,y) => DoSometingWithXY(x,y); () => Console.WriteLine("I do not have parameters!");
在我们的例子中,我们没有任何参数,所以我们将使用最后一个expression式。 我们可以像OnButtonClick函数一样使用它,但是我们获得了没有命名函数的优点。 我们可以做这样的事情:
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
甚至更容易,
Action ButtonClicked = () => MessageBox.Show("Hello World!");
然后简单地调用ButtonClicked();
当然你也可以有多行代码,但我不想让你更困惑。 它会看起来像这样:
Action ButtonClicked = () => { MessageBox.Show("Hello World!"); }; ButtonClicked();
你也可以玩,例如,你可以执行这样的function:
new Action(() => MessageBox.Show("Hello World!"))();
对不起,很长的post,希望它不是太混乱:)
编辑:我忘了提及一个替代forms,即使不经常使用,可以使lambdaexpression式更容易理解:
new Action(delegate() { Console.WriteLine("I am parameterless"); })();
另外,使用generics:
// 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!");
反过来,你可以使用lambdaexpression式,但是你不需要(但可能在某些情况下)来定义参数的types,例如,上面的代码可以简单地写成:
new Action<string>(x => { Console.WriteLine(x); })("I am a string parameter!");
要么:
new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");
EDIT2:
Action<string>
是public void delegate Action(string obj);
Action<string,string>
是public void delegate Action(string obj, string obj2);
通常, Action<T>
是public void delegate Action<T>(T obj);
编辑3:我知道这个post在这里已经有一段时间了,但是我觉得这很酷,不要提到:你可以做到这一点,这主要与你的问题有关:
dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show; aFunction("Hello, world!");
或者干脆:
Func<string, DialogResult> aFunction = MessageBox.Show; aFunction("Hello, world!");
Lazy
类是专门devise用来表示一个值,直到你要求它才会被计算出来。 通过提供一个定义应该如何构build的方法来构造它,但是它将不会一次(甚至在多个线程请求值的情况下)处理该方法的执行,并简单地返回已经构造的值以用于任何其他请求:
var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!")); var result = foo.Value;
我正在阅读你的问题的方式,这是在GUI控件的上下文?
如果这是在WPF中,请看一下“正确”的方式来处理来自控件的命令: http : //msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx
…但这可能是一个痛苦和矫枉过正 对于更简单的一般情况,您可能正在寻找一个事件处理程序,如:
myButton.Click += (o, e) => MessageBox.Show("Hello, World!");
该事件处理程序可以通过多种方式进行处理。 上面的例子使用了一个匿名函数,但是你也可以这样做:
Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World"); myButton.Click += new RoutedEventHandler(sayHello);
…就像你问的那样,用一个函数(或者这里,“Action”,因为它返回void)被赋值为一个variables。
您可以将C#代码分配给一个variables,在运行时编译它并运行代码:
-
写下你的代码:
// Assign C# code to the code variable. string code = @" using System; namespace First { public class Program { public static void Main() { " + "Console.WriteLine(\"Hello, world!\");" + @" } } } ";
-
创build编译器的提供者和参数:
CSharpCodeProvider provider = new CSharpCodeProvider(); CompilerParameters parameters = new CompilerParameters();
-
定义编译器的参数:
// 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;
-
编译汇编:
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
-
检查错误:
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()); }
-
获取程序集,types和Main方法:
Assembly assembly = results.CompiledAssembly; Type program = assembly.GetType("First.Program"); MethodInfo main = program.GetMethod("Main");
-
运行:
main.Invoke(null, null);
参考:
http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime