0

这个让我很困惑,所以我想我会在这里问,希望 C# 大师可以向我解释。

为什么这段代码会产生错误?

        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);
4

2 回答 2

2

=>像一个 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
于 2013-06-11T08:27:30.380 回答
1

这可能与此问题中的原因相同

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

于 2013-06-11T08:26:04.947 回答