C#编译器没有将yield return方法识别为类似?

mhe*_*rle 10 c# compiler-construction yield-return compiler-bug visual-studio-2010-sp1

如果我有两个yield return具有相同签名的方法,则编译器似乎没有认识到它们是相似的.

我有两种yield return方法:

    public static IEnumerable<int> OddNumbers(int N)
    {
        for (int i = 0; i < N; i++)
            if (i % 2 == 1) yield return i;
    }
    public static IEnumerable<int> EvenNumbers(int N)
    {
        for (int i = 0; i < N; i++)
            if (i % 2 == 0) yield return i;
    }
Run Code Online (Sandbox Code Playgroud)

有了这个,我希望以下语句编译好:

Func<int, IEnumerable<int>> generator = 1 == 0 ? EvenNumbers : OddNumbers; // Does not compile

我收到错误消息

无法确定条件表达式的类型,因为"方法组"和"方法组"之间没有隐式转换

但是,一个明确的演员工作:

Func<int, IEnumerable<int>> newGen = 1 == 0 ? (Func<int, IEnumerable<int>>)EvenNumbers : (Func<int, IEnumerable<int>>)OddNumbers; // Works fine

我错过了什么或者这是C#编译器中的错误(我使用的是VS2010SP1)?

注意:我已经读过这个并且仍然相信第一个应该编译得很好.

编辑:删除了var代码片段中的用法,因为这不是我想要的.

Luk*_*keH 6

有许多可能的委托类型可以匹配EvenNumbersOddNumbers方法的签名.例如:

  • Func<int, IEnumerable<int>>
  • Func<int, IEnumerable>
  • Func<int, object>
  • 任意数量的自定义委托类型

编译器不会尝试猜测您期望的兼容委托类型.您需要明确并告诉它 - 在您的示例中使用强制转换 - 确切地说您要使用哪种委托类型.

  • @Andrey,一个方法没有内在类型,只有代表才有.这就是三元运算符无法推断返回类型的原因. (4认同)

And*_*rey 6

不,这不是一个bug.它什么都没有yield.的事情是,表达类型method group可以转换为delegate仅当它被直接分配样型:SomeDel d = SomeMeth.

C#3.0规范:

§6.6方法组转换

从方法组(第7.1节)到兼容的委托类型存在隐式转换(第6.1节).

这是方法组唯一可能的隐式转换.

如何根据类型推断评估三元运算符:

A ? B : C:

确保其中任何一个BC可以隐式地转换为彼此的类型.例如A ? 5 : 6.0double因为5可以被隐式转换double.类型AB在这种情况下是method group和之间没有转换method group.只有代表,它可以像你一样强制执行.