C# 使用1 in参数定义的动作委托与2 in参数一起使用

C# 使用1 in参数定义的动作委托与2 in参数一起使用,c#,generics,lambda,C#,Generics,Lambda,鉴于这些定义: public ICommand OkCommand { get; set; } public ModelCommand(Action<object> execute) public RelayCommand(Action<T> execute) public-ICommand-OkCommand{get;set;} 公共模型命令(操作执行) 公共中继命令(操作执行) 此代码编译: this.OkCommand = new ModelCommand(

鉴于这些定义:

public ICommand OkCommand { get; set; }

public ModelCommand(Action<object> execute)

public RelayCommand(Action<T> execute)
public-ICommand-OkCommand{get;set;}
公共模型命令(操作执行)
公共中继命令(操作执行)
此代码编译:

this.OkCommand = new ModelCommand(x => this.Ok(this, new EventArgs()));

this.OkCommand = new RelayCommand<ThisType>(x => this.Ok(this, new EventArgs()));

this.OkCommand = new RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
this.OkCommand=newmodelcommand(x=>this.Ok(this,neweventargs());
this.OkCommand=newrelaycommand(x=>this.Ok(this,neweventargs());
this.OkCommand=newrelaycommand(x=>this.Ok(this,neweventargs());
然而,我很困惑为什么要编译它,以及我是否正确理解它。
在这两种情况下,
Action
方法在参数中有1个
,而函数
this.Ok
有2个。
操作
委托如何处理参数,它接收哪个参数以及原因?

但是您的构造函数只接受一个参数,它被称为
x
。你可以翻译:

RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
RelayCommand(x=>this.Ok(this,neweventargs());
进入:

RelayCommand(委托(事件参数x)
{
this.Ok(this,neweventargs());
});
甚至:

RelayCommand<EventArgs>(SomeTemporaryDelegate);

public void SomeTemporaryDelegate(EventArgs x)
{
    this.Ok(this, new EventArgs());
}
RelayCommand(某个临时代理);
public void SomeTemporaryDelegate(EventArgs x)
{
this.Ok(this,neweventargs());
}

这也许会澄清问题。您只是没有在委托内部使用
x
,而是使用外部变量作为参数。

但是您的构造函数只接受一个参数-它被称为
x
。你可以翻译:

RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
RelayCommand(x=>this.Ok(this,neweventargs());
进入:

RelayCommand(委托(事件参数x)
{
this.Ok(this,neweventargs());
});
甚至:

RelayCommand<EventArgs>(SomeTemporaryDelegate);

public void SomeTemporaryDelegate(EventArgs x)
{
    this.Ok(this, new EventArgs());
}
RelayCommand(某个临时代理);
public void SomeTemporaryDelegate(EventArgs x)
{
this.Ok(this,neweventargs());
}

这也许会澄清问题。您只是没有在委托内部使用
x
,而是使用外部变量作为参数。

每个
操作
都使用一个参数,在本例中,该参数在执行命令时传递到命令中。因此,在以下情况下:

this.OkCommand = new RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
看起来像
Ok
将as
EventArgs
作为第二个参数

这对我来说是一样的:

this.OkCommand = new RelayCommand<ThisType>(x => this.Ok(this, new EventArgs()));

这可能更清楚,因为它表明您对命令参数不感兴趣。

每个
操作
都会获取一个参数,在本例中,该参数在命令执行时传递到命令中。因此,在以下情况下:

this.OkCommand = new RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
this.OkCommand = new ModelCommand(x => this.Ok(this, new EventArgs()));
看起来像
Ok
将as
EventArgs
作为第二个参数

这对我来说是一样的:

this.OkCommand = new RelayCommand<ThisType>(x => this.Ok(this, new EventArgs()));
这可能更清楚,因为它表明您对命令参数不感兴趣

this.OkCommand = new ModelCommand(x => this.Ok(this, new EventArgs()));
在本例中,当调用
this.OkCommand()时

  • 将调用
    ModelCommand
    委托,该委托:
  • 将计算其表达式,其中
  • 将计算表达式中包含的
    Ok
    调用,该调用
  • 将计算调用中包含的参数,其中
  • 将计算
    ,它是一个“闭包”(即捕获的变量),作为封闭对象和
    新事件args()
tl;dr:当您调用
Ok命令时,您不会直接调用
Ok
。相反,
OkCommand
将调用
RelayCommand
,该命令包含正确调用
Ok
所需的所有信息

在本例中,当调用
this.OkCommand()时

  • 将调用
    ModelCommand
    委托,该委托:
  • 将计算其表达式,其中
  • 将计算表达式中包含的
    Ok
    调用,该调用
  • 将计算调用中包含的参数,其中
  • 将计算
    ,它是一个“闭包”(即捕获的变量),作为封闭对象和
    新事件args()

tl;dr:当您调用
Ok命令时,您不会直接调用
Ok
。相反,
OkCommand
将调用
RelayCommand
,该命令具有正确调用
Ok

所需的所有信息当您编写匿名委托或lambda表达式时,您可以使用当前作用域中的任何成员,而不仅仅是传递给该方法的参数。编译器创建一个闭包,该闭包捕获lambda执行所需的所有内容

因此,您的代码大致翻译为:

private class MyClass
{
    public MyClass()
    {
        var closure = new <>c__DisplayClass1 { _this = this };
        OkCommand = new ModelCommand(new Action<object>(closure.b__0));
    }

    [CompilerGenerated]
    private sealed class <>c__DisplayClass1
    {
        public MyClass _this;

        public void b__0(object o)
        {
            return _this.Ok(_this, new EventArgs());
        }
    }
}
私有类MyClass
{
公共MyClass()
{
var closure=newc_uudisplayClass1{uu this=this};
OkCommand=newmodelcommand(新操作(closure.b_uu0));
}
[编译生成]
专用密封c类显示器Class1
{
公共MyClass(本课程);
公共无效b__0(对象o)
{
返回_this.Ok(_this,new EventArgs());
}
}
}
b_uu0
方法匹配
Action
签名,生成的类包含lambda中引用的所有字段


由于这种行为,闭包扩展了在闭包中捕获的字段的范围,因此您必须知道将lambda发送到何处,否则可能会遇到不必要的内存泄漏。

当您编写匿名委托或lambda表达式时,您可以使用当前范围中的任何成员,而不仅仅是传递给方法的参数。编译器创建一个闭包,该闭包捕获lambda执行所需的所有内容

因此,您的代码大致翻译为:

private class MyClass
{
    public MyClass()
    {
        var closure = new <>c__DisplayClass1 { _this = this };
        OkCommand = new ModelCommand(new Action<object>(closure.b__0));
    }

    [CompilerGenerated]
    private sealed class <>c__DisplayClass1
    {
        public MyClass _this;

        public void b__0(object o)
        {
            return _this.Ok(_this, new EventArgs());
        }
    }
}
私有类MyClass
{
公共MyClass()
{
var closure=newc_uudisplayClass1{uu this=this};
OkCommand=newmodelcommand(新操作(closure.b_uu0));
}
[编译生成]
专用密封c类显示器Class1
{
公共MyClass(本课程);
公共无效b__0(对象o)
{
把这个还给你,好吗