C# 将代码赋给变量

C# 将代码赋给变量,c#,variables,C#,Variables,是否可以生成一个变量,并为其分配一行代码,例如: ButtonClicked = (MessageBox.Show("Hello, World!")); 。。。因此,当我使用该变量时,它将执行代码行。您可以将其分配给如下类型的: var ButtonClicked = new Action(() => MessageBox.Show("hi")); Action ButtonClicked = new Action( () => MessageBox.Show("Hello Wo

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

ButtonClicked = (MessageBox.Show("Hello, World!"));
。。。因此,当我使用该变量时,它将执行代码行。

您可以将其分配给如下类型的:

var ButtonClicked = new Action(() => MessageBox.Show("hi"));
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
new Action(() => MessageBox.Show("Hello World!"))();
那就叫它:

ButtonClicked();
为了完整性(关于各种评论)

正如Erik所说,您可以执行多行代码:

var ButtonClicked = new Action(() =>
{
    MessageBox.Show("hi");

    MessageBox.Show("something else");  // something more useful than another popup ;)
});
正如Tim所说,您可以省略
操作
关键字

Action ButtonClicked = () => MessageBox.Show("hi");

Action ButtonClicked = () =>
{
    // multiple lines of code
};
为了回应KRyan关于空括号的评论,它表示您希望能够发送到操作的参数列表(在本例中,无)

例如,如果您想指定要显示的消息,可以添加“message”作为参数(注意,为了指定单个字符串参数,我将
Action
更改为):

Action按钮点击=(消息)=>MessageBox.Show(消息);
按钮点击(“你好,世界!”);
该类专门设计用于表示一个值,该值在您要求时才会计算。您可以通过提供一个方法来构造它,该方法定义了应该如何构造它,但它将处理执行该方法不超过一次(即使在多个线程请求该值的情况下)并简单地为任何其他请求返回已构造的值:

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

var result = foo.Value;
var foo=newlazy(()=>MessageBox.Show(“你好,世界!”);
var结果=foo.Value;

按照我理解您问题的方式,这是在GUI控件的上下文中

如果是在WPF中,请查看处理控件命令的“正确”方法:

…但这可能是一种痛苦和过度的杀伤力。对于更简单的一般情况,您可能需要一个事件处理程序,如:

myButton.Click += (o, e) => MessageBox.Show("Hello, World!");
可以通过多种方式处理该事件处理程序。上述示例使用匿名函数,但您也可以执行以下操作:

Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World");
myButton.Click += new RoutedEventHandler(sayHello);
Action sayHello=(o,e)=>MessageBox.Show(“你好,世界”);
myButton.Click+=新建路由EventHandler(说你好);

…就像您所问的那样,将函数(或此处的“Action”,因为它返回void)指定为变量。

在您的情况下,您希望使用
委托

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

// 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);
我们基本上创建了一个名为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库已经定义了许多委托,其中有些委托具有类似的操作,它们不接受任何参数,也不返回值。定义为
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函数一样使用它,但是我们没有命名函数的优点。我们可以这样做:

var ButtonClicked = new Action(() => MessageBox.Show("hi"));
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
new Action(() => MessageBox.Show("Hello World!"))();
甚至更容易

Action ButtonClicked = () => MessageBox.Show("Hello World!");
然后只需调用
ButtonClicked()
Action ButtonClicked = () => 
{
    MessageBox.Show("Hello World!");
};
ButtonClicked();
您也可以玩游戏,例如,您可以执行如下函数:

var ButtonClicked = new Action(() => MessageBox.Show("hi"));
Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
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!");
或者简单地说:

Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");
Func affunction=MessageBox.Show;
函数(“你好,世界!”);
您可以将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;
    
  • 定义编译器的参数:

    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());
    }
    
  • 获取程序集、类型和主要方法:

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

    main.Invoke(null, null);
    
参考:


操作按钮点击=()=>MessageBox.Show(“嗨”)
是等效的,而且我觉得更好(如果您愿意,可以添加参数),操作也可以解析为多行代码。@CSharpie我不确定这样的假设对OP是否有帮助。@CSharpie为什么OP不能在
WinForms
中使用此选项?@CSharpie我明白您的意思。如果他真的将其附加到一个
按钮上。单击
事件,而不是将其存储在一个他碰巧命名为
按钮的变量中。单击
+1是因为他不熟悉编码并提出了一个好问题,这是一个罕见的组合:你了解你想要做什么,并且解释得很好,你只是不知道它的术语,所以你自己找不到。你要找的术语是一个。看看这个,我想你需要足够的解释。Asp在这方面的工作原理几乎与winforms类似。听起来很像Objective cRemember中的块,即
惰性
应用于需要大量处理能力的值,而不应将它们用于交互(因为
.Value
的语义是它返回一个值,