10

同じシグニチャを持つ2つのyield returnメソッドがある場合、コンパイラはそれらが類似していると認識していないようです。

私はyield returnこのような2つの方法があります:

    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

EvenNumbersおよびメソッドのシグニチャに一致する可能性のあるデリゲートタイプは多数ありOddNumbersます。例えば:

  • 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

BまたはCがお互いのタイプに暗黙的にキャストできることを確認してください。たとえば、5を暗黙的ににキャストA ? 5 : 6.0できるdoubleため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に設定しているのではなくIEnumerable<int>、に設定しているMethodGroup、つまり、呼び出しを行うための角かっこなしの関数です。

2番目のステートメントは、比較可能なMethodGroupsをsにキャストします。Delegate

おそらくあなたは次のようなことをするつもりですが、

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 に答える