[英]how to convert optional parameter method to delegate in c#
我有一个铸造问题。
public void Test(int a = 0) { }
System.Action d = Test;
此代码在5合一中效果很好。
但是Visual Studio 2015无法对其进行编译。
CS0123'测试'的重载不匹配代表'动作'
为什么???
调用带有可选参数的方法时,实际上会将其编译为带有这些参数的参数值的调用,这些值由方法的声明的默认值确定。
如果您有一个这样声明和使用的方法:
public void Foo(String x = "foo", Int32 y = 123) {
// do something
}
public void Bar() {
Foo();
}
然后编译它,并查看程序集中生成的CIL,您会看到Bar
实际上正在这样做:(与编译器使用已编译的CIL和调用约定(例如C风格的可变参数函数)进行一些伏都教一样
public void Bar() {
Foo("foo", 123);
}
(这也解释了为什么默认值必须是编译时常量(因为它们实际上是逐字放置在调用代码中),并且应注意,如果在一个程序集中更改可选参数的默认值的值而不重新编译调用然后使用旧值(就像public const
一样)。
我的观点是,带有可选参数的方法在形式上仍然仍然是多参数方法,这就是为什么带有参数子集的委托无法绑定到它的原因。
因此,您将需要提供另一个方法重载,它是一个真正的零参数,或者将其包装在一个匿名函数中:
public void Test(Int32 a = 0) {}
public void Test() {}
Action d = Test;
要么:
Action d = () => Test();
我很惊讶它可以在Unity中工作-不行。 这听起来像是Mono编译器的错误。
C#5规范对此并不十分清楚,但是从即将到来的ECMA C#5标准的草案中,从关于方法组转换的子句中着重强调:
- 选择对应于形式
E(A)
的方法调用的单个方法M,并进行以下修改:
- 参数列表
A
是一个表达式列表,每个表达式都被分类为一个变量,并且具有D
的形式参数列表中相应参数的类型和修饰符(ref
或out
)-dynamic
类型的参数除外,其中相应的表达式具有类型object
而不是dynamic
。- 所考虑的候选方法仅是那些以其正常形式适用且不省略任何可选参数的方法 。 因此,如果候选方法仅以其扩展形式适用,或者其一个或多个可选参数在
D
没有对应的参数,则将忽略这些候选方法。
最简单的解决方法是使用lambda表达式,如Dai所说:
Action d = () => Test();
当使用委托进行类型检查时,编译器显然将忽略可选参数的“可选”性,并认为它们是必需的。
您可以声明自己的委托类型来解决此问题:
public delegate void MyDel(int i = 1); // this 1 here can be any number. It does not seem to matter
//...
MyDel d = Test;
d();
或者,您可以只添加一点() =>
以在lambda中调用Test
:
Action d = () => Test();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.