使用具有匿名函数的三元运算符时编译错误

时间:2013-06-11 08:11:24

标签: c# ternary-operator

这个让我感到沮丧,所以我想我会在这里问,希望C#guru可以向我解释。

为什么此代码会产生错误?

        Func<IEnumerable<Item>, IEnumerable<Item>, IEqualityComparer<Item>, IEnumerable<Item>> func = strict ?
            (first, second, comparer) => first.Intersect(second, comparer) :
            (first, second, comparer) => first.Union(second, comparer);

虽然这个没有:

        Func<IEnumerable<Item>, IEnumerable<Item>, IEqualityComparer<Item>, IEnumerable<Item>> func1;
        if (strict)
            func1 = (first, second, comparer) => first.Intersect(second, comparer);
        else
            func1 = (first, second, comparer) => first.Union(second, comparer);

2 个答案:

答案 0 :(得分:1)

它可能与this question

中的原因相同

如果将“func1 =”添加到三元表达式中,编译错误应该消失

答案 1 :(得分:1)

lambda =>喜欢

(first, second, comparer) => first.Intersect(second, comparer)

本身并不具备某种类型。但它可以隐式转换为与签名和返回类型匹配的所有委托类型。它也可以(有一些例外)转换为Expression<Del>Del就是这样的代表。

当您将lambda箭头直接分配给func1变量时,编译器确切地知道要转换为哪种委托类型。这样可行(你的第二个例子)。

在第一个例子中:

strict ?
(first, second, comparer) => first.Intersect(second, comparer) :
(first, second, comparer) => first.Union(second, comparer)

(在我们进入func的任务之前)编译器首先必须在冒号:的每一侧找到两种类型的最佳公共类型。但正如我所说,一个lambda箭头没有类型,所以失败了。如果你说:

,它会奏效
strict ?
(Func<IEnumerable<Item>, IEnumerable<Item>, IEqualityComparer<Item>, IEnumerable<Item>>)((first, second, comparer) => first.Intersect(second, comparer)) :
(Func<IEnumerable<Item>, IEnumerable<Item>, IEqualityComparer<Item>, IEnumerable<Item>>)((first, second, comparer) => first.Union(second, comparer))

但当然这很难看。 (实际上,你只需要将两个lambda中的一个赋予它一个类型,另一个将自动获得相同的类型。)

增加:

类似的事情发生在null关键字上,它本身也没有类型,但可以隐式转换为很多类型(如string)。所以这有效:

string myString1 = null;

而这些不是:

var myString2 = null;                    // need to cast null to a type, to use var
string myString3 = strict ? null : null; // cast at least one null, to use ternary op