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

=>のようなラムダ矢印

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

型自体は持っていません。ただし、署名と戻り値の型に一致するすべてのデリゲート型に暗黙的に変換できます。また、(いくつかの例外はありますが)そのようなデリゲートのExpression<Del>場所に変換できます。Del

ラムダ矢印を変数に直接割り当てるfunc1と、コンパイラは変換先のデリゲート型を正確に認識します。それでうまくいきます(2番目の例)。

最初の例では:

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

( への割り当てに入る前にfunc) コンパイラはまず、コロン の両側にある 2 つの型の中で最も一般的な型を見つけなければなりません:。しかし、先ほど言ったように、ラムダ矢印には型がないため、失敗します。あなたが言ったならそれはうまくいくでしょう:

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

もちろん、それは醜いです。(実際には、2 つのラムダの1 つをキャストして型を指定するだけでよく、もう 1 つのラムダは同じ型を自動的に取得します。)

添加:

同様のことが、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 に答える