10

如果我有两个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;
    }

有了这个,我希望下面的语句编译得很好:

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代码片段中的使用,因为这不是我想要问的。

4

8 回答 8

6

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

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

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

于 2011-07-22T11:53:10.423 回答
6

不,这不是错误。它与yield. 问题是表达式类型只有在直接赋值时method group才能转换为类型: .delegateSomeDel d = SomeMeth

C# 3.0 规范

§6.6 方法组转换

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

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

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

A ? B : C

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

于 2011-07-22T11:58:27.777 回答
1

好吧,甚至

var gen = OddNumbers;

不起作用。所以你不能指望三元运算符起作用。

我猜 var 无法推断出委托类型。

于 2011-07-22T12:00:51.647 回答
1

与此yield Return无关。

您没有设置generator为 a IEnumerable<int>,而是将其设置为 a MethodGroup,即不带括号的函数来进行调用。

第二个语句将MethodGroups转换为Delegate可以比较的 s。

也许你的意思是做类似但是,

var generator = 1 == 0 ? EvenNumbers(1) : OddNumbers(1);

我不能肯定地说。

于 2011-07-22T12:01:08.470 回答
1

它与迭代器没有任何关系,如果方法是简单的函数,相同的代码将无法编译。编译器不愿意自动将方法转换为委托对象,忘记在方法调用中使用 () 是很常见的错误。你必须明确地做到这一点。

于 2011-07-22T12:10:07.577 回答
1

有效和无效的汇总:

不工作:

var generator = 1 == 0 ? EvenNumbers : OddNumbers;
Func<int, IEnumerable<int>> generator = 1 == 0 ? EvenNumbers : OddNumbers;

是否有效:

var generator = 1 == 0 ? (Func<int, IEnumerable<int>>)EvenNumbers : OddNumbers;

如果有任何关系,yield或者var后者也应该失败。

我的猜测是三元运算符的问题。

于 2011-07-22T12:22:09.413 回答
0

问题是声明

var gen = OddNumbers;

都可以理解为

Func<int, IEnumerable<int>> gen = OddNumbers;

Expression<Func<int, IEnumerable<int>> gen = OddNumbers;

编译器无法决定,所以你必须这样做。

于 2011-07-22T12:09:30.030 回答
0

方法(方法组)没有内在类型,只有委托才有。这就是为什么三元运算符不能推断要返回的类型的原因,因此您必须将一个或另一个返回值强制转换为要返回的类型。

于 2011-07-22T12:14:08.013 回答