9

给定以下课程:

public class MyType
{
    public static implicit operator MyType(Func<MyType> wrapper) {
        return wrapper();
    }
}

从 to 的隐式Func<MyType>转换MyType,我假设以下是可能的:

public MyType MyTypeWrapper() {
    return new MyType();
}

public void MyTestMethod() {
    MyType m = MyTypeWrapper; // not a call!
}

但是我得到:

无法将方法组“MyTypeWrapper”转换为非委托类型“Test.MyType”。您是否打算调用该方法?

对我来说不幸的是,当搜索时(正如我的一半预期)导致大量 问题 答案是:

嘿,你没搞错;折腾()到底WhateverMethod

现在,当我输入这个时,我注意到显式强制转换实际上可以编译:

MyType m = (MyType) MyTypeWrapper;

为什么我不能像我所描述的那样隐式地将 aFunc<MyType>转换为?MyType

4

4 回答 4

12

这是不幸的。我很确定您已经发现了一个编译器错误,并且规范的这一部分非常难以阅读。

C# 4 规范的第 6.4.4 节解释了为什么你的隐式转换是非法的。

算法是这样的。首先看源类型和目标类型。没有源类型,因为方法组没有类型。目标类型是MyType。所以搜索MyType用户定义的隐式转换。现在的问题是:从包含 S 的类型转换的适用的用户定义运算符的集合是什么? S是源类型,我们已经确定没有源类型。所以这已经是转换应该失败的证据。但是,即使编译器出于某种原因决定您的Func<MyType>转换适用,该规则也是标准的隐式转换 ... is executed方法组转换故意不归类为标准转换.

所以这就是为什么它应该是非法的。

那么为什么显式强制转换是合法的呢?

没有理由这样做。这似乎是一个错误。

这是不幸的;许多人为错误道歉。我会向我以前的同事报告;如果他们的分析与我的冲突,我会更新答案。

更新:我以前的同事告诉我,假定源表达式具有类型的规范问题将在规范的下一个版本中通过改写来解决。目前还没有关于显式转换行为是否是错误的消息。

于 2013-06-14T20:42:36.230 回答
11

您已经在使用从方法组Func<MyType>.

编译器不会同时进行两次隐式转换。

一旦你对你的类进行了显式强制转换,编译器就知道要寻找任何可以显式强制转换到你的类的类型的隐式强制转换。

于 2013-06-14T20:03:02.597 回答
1

因为 C# 编译器无法转换MyTypeWrapperFunc<MyType>(MyTypeWrapper). 方法组和实际委托之间存在差异。

这编译并运行良好:

MyType m = new Func<MyType>(MyTypeWrapper);

存在从方法组到与该组匹配的委托类型的隐式转换,并且存在用户定义的从该委托到类型的隐式转换。这里的一般想法是编译器一次只会连续使用一个隐式转换。当它有一个 A 并且需要一个 C 时,它会查找从 A 到 C 的转换,而不是从 A 到任何类型 B 以及从该类型到 C 的转换。该算法从 O(n) 到 O(n^2)(而不是提到可能会让程序员感到困惑)。

您的代码在使用显式转换时起作用的原因MyType是您不再链接隐式转换。

于 2013-06-14T20:02:50.307 回答
1

的签名MyTestMethodMATCHES 的签名Func<MyType>但不是Func<MyType>. Func 自己定义了一些隐式转换,以允许您分配诸如 Func 之类的方法,但您必须显式转换才能应用签名,因为编译器不会为您将隐式转换链接在一起:

MyType m = (Func<MyType>)MyTypeWrapper; // not a call!
于 2013-06-14T20:06:07.743 回答