鉴于以下课程:
public class MyType
{
public static implicit operator MyType(Func<MyType> wrapper) {
return wrapper();
}
}
从隐式演员Func<MyType>
到MyType
,我认为以下内容是可能的:
public MyType MyTypeWrapper() {
return new MyType();
}
public void MyTestMethod() {
MyType m = MyTypeWrapper; // not a call!
}
但是我得到了:
无法将方法组“MyTypeWrapper”转换为非委托类型“Test.MyType”。你打算调用这个方法吗?
对我而言,不幸的是,在搜索时(正如我预期的那样)导致tons of questions答案是:
嘿,你的傻瓜;在()
!的末尾掷出WhateverMethod
现在,当我输入此内容时,我注意到显式强制转换确实会编译:
MyType m = (MyType) MyTypeWrapper;
为什么我不能像我所描述的那样隐含地将Func<MyType>
投射到MyType
?
答案 0 :(得分:12)
这很不幸。我很确定你发现了编译器错误,而且规范的这一部分非常难以阅读。
C#4规范的第6.4.4节解释了为什么隐式转换是非法的。
算法是这样的。首先看一下源类型和目标类型。没有源类型,因为方法组没有类型。目标类型为MyType
。因此,搜索MyType
以获取用户定义的隐式转换。现在的问题是:什么是适用的用户定义运算符集...从包含S 的类型转换? S
是源类型,我们已经确定没有源类型。所以这已经证明转换失败了。但即使编译器出于某种原因决定您的Func<MyType>
转换适用,规则也是标准隐式转换...执行。 方法组转化有意未被归类为标准转化。
这就是为什么它应该是非法的。
为什么显性演员合法呢?
没有理由这样做。这似乎是一个错误。
这很不幸;许多道歉的错误。我会向以前的同事报告;如果他们的分析与我的相冲突,我会更新答案。
更新:我的前同事告诉我,源表达式假定具有类型的规范问题将通过规范的下一版本中的重新措辞来解决。还没有关于显式演员行为是否是一个错误的消息。
答案 1 :(得分:11)
您已使用从方法组到Func<MyType>
的内置隐式转换。
编译器不会一次进行两次隐式转换。
一旦你对你的类进行了显式强制转换,编译器就会知道对任何可以显式地转换为你的类的类型进行隐式转换。
答案 2 :(得分:1)
因为C#编译器无法将MyTypeWrapper
转换为Func<MyType>(MyTypeWrapper)
。方法组和实际委托之间存在差异。
编译并运行良好:
MyType m = new Func<MyType>(MyTypeWrapper);
从方法组到与该组匹配的委托类型的隐式转换,并且您的用户定义了从该委托到类型的隐式转换。这里的一般想法是编译器一次只能在一行中使用一个隐式转换。当它有A并需要C时,它会查找从A到C的转换,而不是从A到任何类型B以及从该类型到C的转换。该算法从O(n)变为O(n ^ 2)(不是提到程序员可能会很困惑。)
使用显式转换为MyType
时代码的工作原因是您不再链接隐式转换。
答案 3 :(得分:1)
MyTestMethod
的签名与Func<MyType>
的签名匹配,但不是Func<MyType>
。 Func已经定义了一些隐式强制转换,允许您将这些方法指定为Funcs,但是您必须显式转换为要应用的签名,因为编译器不会为您链接隐式强制转换:
MyType m = (Func<MyType>)MyTypeWrapper; // not a call!