为变量分配代码

是否可以创建一个变量,并为其分配一行代码,例如:

ButtonClicked = (MessageBox.Show("Hello, World!"));

... 所以当我使用变量时,它会执行代码行。

7202 次浏览

你可以把它分配给像这样的 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”作为参数 (note that I changed Action to Action<string> 以指定单个字符串参数):

Action<string> ButtonClicked = (message) => MessageBox.Show(message);


ButtonClicked("hello world!");

Lazy类是专门设计用来表示一个直到您要求时才会被计算的值。你可以通过提供一个方法来构造它,这个方法定义了它应该如何构造,但是它只会执行这个方法一次(即使是在多个线程请求这个值的情况下) ,并且对于任何额外的请求只返回已经构造好的值:

var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));


var result = foo.Value;

我理解你的问题的方式,这是在 GUI 控件的上下文中吗?

If this is in WPF, take a look at the "right" way to handle commands from controls: 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)作为一个变量赋值。

在您的例子中,您需要使用 delegate

让我们看看一个代表是如何工作的,以及我们如何通过理解它的概念来获得一个更简单的形式:

// Create a normal function
void OnButtonClick()
{
MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();

You see, the delegate takes the form of a normal function but without any arguments (It could take any amount of arguments just like any other method, but for the sake of simplicity, it doesn't).

现在,让我们使用我们所有的; 我们将定义委托,就像我们定义任何其他变量一样:

ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);

我们基本上创建了一个名为 ButtonClick 的新变量,该变量具有 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();
You can always use it to your needs instead of the need of defining a new delegate every time. In the previous context for example, you could had just written

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!");

编辑2:
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: 我知道这个帖子已经有一段时间了,但是我觉得不提这个真的很酷: 你可以这样做,这主要与你的问题有关:

dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");

or simply:

Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");

您可以为一个变量分配 C # 代码,在运行时编译它并运行代码:

  • Write your code:

    // Assign C# code to the code variable.
    string code = @"
    using System;
    
    
    namespace First
    {
    public class Program
    {
    public static void Main()
    {
    " +
    "Console.WriteLine(\"Hello, world!\");"
    + @"
    }
    }
    }
    ";
    
  • Create the provider and parameters of the compiler:

    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerParameters parameters = new CompilerParameters();
    
  • Define parameters of the compiler:

    // 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;
    
  • Compile assembly:

    CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
    
  • Check errors:

    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());
    }
    
  • Get assembly, type and the Main method:

    Assembly assembly = results.CompiledAssembly;
    Type program = assembly.GetType("First.Program");
    MethodInfo main = program.GetMethod("Main");
    
  • Run it:

    main.Invoke(null, null);
    

Reference:

http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime