将代码分配给变量

时间:2014-04-16 20:39:35

标签: c# variables

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

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

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

5 个答案:

答案 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