是否可以创建变量,并为其分配一行代码,例如:
ButtonClicked = (MessageBox.Show("Hello, World!"));
...所以当我使用变量时,它将执行代码行。
答案 0 :(得分:89)
您可以将其分配给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 ;)
});
正如蒂姆所说,你可以省略Action
关键字
Action ButtonClicked = () => MessageBox.Show("hi");
Action ButtonClicked = () =>
{
// multiple lines of code
};
要解决KRyan的评论,关于空括号,表示您希望能够发送到Action 的参数列表(在本例中为none)。
例如,如果您要指定要显示的消息,可以添加“消息”作为参数(请注意,我已将 Action
更改为 Action<string>
以指定单个字符串参数):
Action<string> ButtonClicked = (message) => MessageBox.Show(message);
ButtonClicked("hello world!");
答案 1 :(得分:51)
在您的情况下,您想使用delegate
。
让我们看看代表是如何运作的,以及我们如何通过理解其概念来获得更简单的形式:
// Create a normal function
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();
你看,委托采用普通函数的形式但没有任何参数(它可以像任何其他方法一样接受任何数量的参数,但为了简单起见,它没有)。
现在,让我们用我们拥有的东西;我们将定义委托,就像我们定义任何其他变量一样:
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
我们基本上创建了一个名为ButtonClicked的新变量,它有一种ButtonClick(它是一个委托),使用时会在OnButtonClick()方法中执行该方法。
要使用它,我们只需致电:ButtonClicked();
所以整个代码是:
delegate void ButtonClick();
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
void Foo()
{
ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
ButtonClicked(); // Execute the function.
}
从这里开始,我们可以转到lambda表达式,看看它们在你的情况下是如何有用的:
.NET库已经定义了许多委托,其中一些委托像Action,它们不接受任何参数并且不返回值。它被定义为public delegate void Action();
您始终可以根据需要使用它,而不是每次都需要定义新的委托。例如,在上一个上下文中,您可能刚刚编写了
Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();
也会这样做。
既然您已经看到了如何使用委托的不同方法,那么让我们使用我们的第一个lambda表达式。 Lambda表达式是匿名函数;所以,它们是正常的功能但没有名字。它们具有以下形式:
x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");
在我们的例子中,我们没有任何参数,所以我们将使用最后一个表达式。我们可以像OnButtonClick函数一样使用它,但是我们可以获得没有命名函数的优点。我们可以做这样的事情:
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
甚至更容易,
Action ButtonClicked = () => MessageBox.Show("Hello World!");
然后简单地调用ButtonClicked();
当然,您也可以使用多行代码,但我不想让您更加困惑。虽然看起来像这样:
Action ButtonClicked = () =>
{
MessageBox.Show("Hello World!");
};
ButtonClicked();
你也可以玩,例如,你可以执行这样的功能:
new Action(() => MessageBox.Show("Hello World!"))();
很抱歉这篇长篇文章,希望它不会太混乱:)。
编辑:我忘了提到一个替代形式,即使不经常使用,也可以使lambda表达式更容易理解:
new Action(delegate() {
Console.WriteLine("I am parameterless");
})();
另外,使用泛型:
// 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!");
反过来你可以使用lambda表达式,但你不需要(但在某些情况下可能)来定义参数的类型,例如,上面的代码可以简单地写成:
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);
EDIT3: 我知道帖子已经存在了一段时间,但我认为这真的很酷,没有提到: 你可以这样做,这主要与你的问题有关:
dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");
或简单地说:
Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");
答案 2 :(得分:7)
Lazy
类专门用于表示在您要求之前不会计算的值。你通过提供一个定义它应该如何构造的方法来构造它,但是它将处理执行该方法不超过一次(即使面对多个线程请求值)并且只是为任何其他请求返回已构造的值:
var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));
var result = foo.Value;
答案 3 :(得分:4)
我在阅读您的问题的方式,这是在GUI控件的上下文中?
如果这是在WPF中,请查看&#34;右键&#34;处理来自控件的命令的方法: 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);
...就像你问的那样,用一个函数(或者这里,&#34; Action&#34;,因为它返回void)被指定为一个变量。
答案 4 :(得分:1)
您可以将C#代码分配给变量,在运行时编译它并运行代码:
编写代码:
// Assign C# code to the code variable.
string code = @"
using System;
namespace First
{
public class Program
{
public static void Main()
{
" +
"Console.WriteLine(\"Hello, world!\");"
+ @"
}
}
}
";
创建编译器的提供程序和参数:
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());
}
获取程序集,类型和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