鉴于这些定义:
public ICommand OkCommand { get; set; }
public ModelCommand(Action<object> execute)
public RelayCommand(Action<T> execute)
此代码编译:
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()));
但是我很困惑,为什么这个编译以及我是否理解正确
在这两种情况下,Action
方法都有1个in
参数,而函数this.Ok
有2个。
参数如何处理Action
委托,接收哪个参数以及为什么?
答案 0 :(得分:1)
但是你的构造函数只取一个参数 - 它被称为x
。你可以翻译:
RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
成:
RelayCommand<EventArgs>(delegate(EventArgs x)
{
this.Ok(this, new EventArgs());
});
甚至:
RelayCommand<EventArgs>(SomeTemporaryDelegate);
public void SomeTemporaryDelegate(EventArgs x)
{
this.Ok(this, new EventArgs());
}
这可能会澄清事情。您只是不使用x
委托内部,使用外部变量作为参数。
答案 1 :(得分:1)
每个Action
都接受一个参数,在这种情况下,参数在执行时传递给命令的命令参数。因此,在以下情况下:
this.OkCommand = new RelayCommand<EventArgs>(x => this.Ok(this, new EventArgs()));
x
将是EventArgs
个实例。该操作对参数没有任何作用,只是直接调用Ok
,尽管它也可以写成:
this.OkCommand = new RelayCommand<EventArgs>(x => this.Ok(this, x));
看起来Ok
的格式为EventArgs
,因为它是第二个参数
对于:
是一样的this.OkCommand = new RelayCommand<ThisType>(x => this.Ok(this, new EventArgs()));
它需要一个ThisType
commanand参数,并且不执行任何操作。
如果你正在使用标准的RelayCommand
类,那么就会有一个非泛型版本只需要一个无参数Action
,这样你就可以写:
this.OkCommand = new RelayCommand(() => this.Ok(this, x));
这可能更清楚,因为它表明你对命令参数不感兴趣。
答案 2 :(得分:1)
this.OkCommand = new ModelCommand(x => this.Ok(this, new EventArgs()));
在这种情况下,当您调用this.OkCommand();
:
ModelCommand
委托,其中:Ok
调用,this
,这是一个“闭包”(即,已捕获的变量),作为封闭对象和new EventArgs()
。 tl; dr:当您调用OkCommand
时,您不会直接致电Ok
。相反,OkCommand
会调用RelayCommand
,其中包含正确调用Ok
所需的所有信息。
答案 3 :(得分:1)
编写匿名委托或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());
}
}
}
b__0
方法与Action<object>
签名匹配,生成的类包含您在lambda中引用的所有字段。
由于这种行为,闭包扩展了其中捕获的字段的范围,因此您必须知道将lambda发送到的位置,否则您可能会遇到不必要的内存泄漏。