我有一个RelayCommand的构造函数,设置为:

public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)

在另一个 playbook 中,我有:

    private Server _server;
    public RelayCommand ConnectToServerCommand {get; set;}

    public MainViewModel() // constructor
    {
        _server = new Server();


        //this syntax is confusing to me - not sure what it's doing
        ConnectToServerCommand = new(o => _server.Connect());
    }

我真的不理解MainViewModel构造函数中ConnectToServerCommand的语法.

RelayCommand接受具有对象参数类型的操作,但_server.Connect()方法具有以下签名:

// Server
public void Connect()

为什么它允许在没有对象作为其参数之一的情况下使用此方法?假设动作设置为Action<object>.它怎么会认为这是有效的方法签名呢?

我对此还是个新手,所以我觉得lambda这个表达让我有点困惑,但我不确定它们在这里是如何联系在一起的.

推荐答案

这种方法

o => _server.Connect()

与此方法相同

void Anon(object o) 
{
    // argument o is ignored
    _server.Connect();
}

使此代码等同于您的代码:

private Server _server;
public RelayCommand ConnectToServerCommand {get; set;}

// un-lambda-ed
void Anon(object o) 
{
    _server.Connect();
}

public MainViewModel() // constructor
{
    _server = new Server();

    // no confusion
    ConnectToServerCommand = new(Anon);
}

让我们在构造函数中有两个调用:

public MainViewModel() // constructor
{
    _server = new Server();

    ConnectToServerCommand = new(o => _server.Connect());
    // no confusion
    ConnectToServerCommand = new(Anon);
}

然后比较生成的中间语言:


MainViewModel:
IL_0000:  ldarg.0     
IL_0001:  newobj      UserQuery+Server..ctor
IL_0006:  stfld       UserQuery._server              // _server = new Server();
IL_000B:  ldarg.0     
IL_000C:  ldarg.0     
IL_000D:  ldftn       UserQuery.<MainViewModel>b__0  // our lamda function, see below
IL_0013:  newobj      System.Action<System.Object>..ctor
IL_0018:  newobj      UserQuery+RelayCommand..ctor
IL_001D:  call        UserQuery.set_ConnectToServerCommand
IL_0022:  ldarg.0     
IL_0023:  ldarg.0     
IL_0024:  ldftn       UserQuery.Anon                 // our Anon call
IL_002A:  newobj      System.Action<System.Object>..ctor
IL_002F:  newobj      UserQuery+RelayCommand..ctor
IL_0034:  call        UserQuery.set_ConnectToServerCommand
IL_0039:  ret         

<MainViewModel>b__0:  // generated by the compiler for us, the lambda
IL_0000:  ldarg.0     // object o, nothing gets done with that
IL_0001:  ldfld       UserQuery._server
IL_0006:  callvirt    UserQuery+Server.Connect
IL_000B:  ret         

Anon:
IL_0000:  ldarg.0     // object o, nothing gets done with that
IL_0001:  ldfld       UserQuery._server
IL_0006:  callvirt    UserQuery+Server.Connect
IL_000B:  ret         

这是惊人的相似.

Csharp相关问答推荐

CsWin32如何创建PWSTR的实例,例如GetWindowText

C#使用属性和值将JSON转换为XML

有没有办法在WPF文本框中添加复制事件的处理程序?

我的MRG32k3a算法实现返回的数字超出了预期的[0,1]范围

Blazor Web App WASM的两个独立项目令人困惑

C#中浮点数的System.Text.Json序列化问题

在C#中反序列化/序列化具有混合元素顺序的XML时出现问题

HttpRequestMessage.SetPolicyExecutionContext不会将上下文传递给策略

Google OAuth令牌交换在.Net中不起作用

如何在onNext之前等待订阅者完成?

如何使用Npgsql从SELECT获得所有查询结果

岛屿和框架中的自定义控件库.Navigate-AccessViolationException

未显示详细信息的弹出对话框

C#无法将.csv列转换为用于JSON转换的列表

VS代码扩展无法在新版本扩展C#中运行从v2.10.28开始

如何在Cake脚本中设置MSBuild.exe的绝对路径

将列表转换为带有逗号分隔字符串形式的值的字典

如何在C#中用Serilog记录类路径、方法名和行编号

C#If条件格式

初始化具有EntityFrameworkCore和不同架构的数据库时引发System.MissingMethodExcept