将代码分配给变量

use*_*891 124 c# variables

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

ButtonClicked = (MessageBox.Show("Hello, World!"));
Run Code Online (Sandbox Code Playgroud)

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

Gra*_*ICA 88

您可以将其指定为Action:

var ButtonClicked = new Action(() => MessageBox.Show("hi"));
Run Code Online (Sandbox Code Playgroud)

然后叫它:

ButtonClicked();
Run Code Online (Sandbox Code Playgroud)

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

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

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

    MessageBox.Show("something else");  // something more useful than another popup ;)
});
Run Code Online (Sandbox Code Playgroud)

正如蒂姆所说,你可以省略Action关键字

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

Action ButtonClicked = () =>
{
    // multiple lines of code
};
Run Code Online (Sandbox Code Playgroud)

要解决KRyan的注释,关于空括号,它表示您希望能够发送到Action的参数列表(在本例中为none).

例如,如果要指定要显示的消息,可以添加"message"作为参数(请注意,我 为了指定单个字符串参数而更改Action ):Action<string>

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

ButtonClicked("hello world!");
Run Code Online (Sandbox Code Playgroud)

  • `Action ButtonClicked =()=> MessageBox.Show("hi");`是等价的,IMO更好(如果你愿意,可以添加parens) (10认同)
  • @CSharpie我不确定这个假设是否对OP有帮助. (2认同)
  • @CSharpie为什么OP不能在`WinForms`中使用它? (2认同)
  • @CSharpie我明白你在说什么.如果他实际上将它附加到`Button.Click`事件,而不是将它存储在他碰巧命名为'ButtonClicked`的变量中. (2认同)

use*_*065 51

在您的情况下,您想使用delegate.

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

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

你看,委托采用普通函数的形式,但没有任何参数(它可以像任何其他方法一样使用任何数量的参数,但为了简单起见,它没有).

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

ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
Run Code Online (Sandbox Code Playgroud)

我们基本上创建了一个名为ButtonClicked的新变量,它有一种ButtonClick(它是一个委托),当使用时,它将在OnButtonClick()方法中执行该方法.
要使用它,我们只需调用:ButtonClicked();

所以整个代码将是:

delegate void ButtonClick();

void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}

void Foo()
{
    ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
    ButtonClicked(); // Execute the function.
}  
Run Code Online (Sandbox Code Playgroud)

从这里开始,我们可以转移到lambda表达式,看看它们在你的情况下是如何有用的:
.NET库已经定义了许多委托,有些像Action,它们不接受任何参数而且不返回值.它被定义为public delegate void Action();
您始终可以根据需要使用它,而不是每次都需要定义新的委托.例如,在上一个上下文中,您可能刚刚编写过

Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();
Run Code Online (Sandbox Code Playgroud)

哪个会做同样的事情.
既然您已经看到了如何使用委托的不同方法,那么让我们使用我们的第一个lambda表达式.Lambda表达式是匿名函数; 所以,它们是正常的功能但没有名字.他们是这些形式:

x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");
Run Code Online (Sandbox Code Playgroud)

在我们的例子中,我们没有任何参数,所以我们将使用最后一个表达式.我们可以像OnButtonClick函数一样使用它,但是我们可以获得没有命名函数的优点.我们可以做这样的事情:

Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
Run Code Online (Sandbox Code Playgroud)

甚至更容易

Action ButtonClicked = () => MessageBox.Show("Hello World!");
Run Code Online (Sandbox Code Playgroud)

然后简单地调用ButtonClicked();当然你也可以有多行代码,但我不想让你更加困惑.它看起来像这样:

Action ButtonClicked = () => 
{
    MessageBox.Show("Hello World!");
};
ButtonClicked();
Run Code Online (Sandbox Code Playgroud)

你也可以玩,例如,你可以执行这样的功能:

new Action(() => MessageBox.Show("Hello World!"))();
Run Code Online (Sandbox Code Playgroud)

对不起,很长的帖子,希望它不是太混乱:)

编辑:我忘了提到一个替代形式,即使不经常使用,可以使lambda表达式更容易理解:

new Action(delegate() {
    Console.WriteLine("I am parameterless");
})();
Run Code Online (Sandbox Code Playgroud)

另外,使用泛型:

// 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!");
Run Code Online (Sandbox Code Playgroud)

反过来你可以使用lambda表达式,但是你不需要(但在某些情况下可能)来定义参数的类型,例如,上面的代码可以简单地写成:

new Action<string>(x => {
    Console.WriteLine(x);
})("I am a string parameter!");
Run Code Online (Sandbox Code Playgroud)

要么:

new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");
Run Code Online (Sandbox Code Playgroud)

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!");
Run Code Online (Sandbox Code Playgroud)

或者干脆:

Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");
Run Code Online (Sandbox Code Playgroud)


Ser*_*rvy 7

Lazy班是专门设计来代表,直到你问它是不会被计算的值.你通过提供一个定义它应该如何构造的方法来构造它,但是它将处理执行该方法不超过一次(即使面对多个线程请求值)并且只是为任何其他请求返回已构造的值:

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

var result = foo.Value;
Run Code Online (Sandbox Code Playgroud)