22

次のコードを想像してください。

class foreach_convert
{
    public static void method2()
    {
        List<IComparable> x = new List<IComparable>();
        x.Add(5);

        foreach (string s in x)
        {
            //InvalidCastException in runtime
        }
    }
}

なぜこの foreach の動作は C# に似ていないのでしょうか? ここで起こるのは、サブクラスへの暗黙のキャストです。これはエラーが発生しやすく、言語の他のすべての場所で禁止されているようです。それとも私は正しくありませんか?

PS私が尋ねている理由は、プロジェクトの同様のコードにバグがあり、以前は like と呼ばれていた外部ライブラリからカスタム コレクションを反復処理していたSomeTypeCollectionが、実際には基本型アイテムのコレクションを提供していたためです。のアイテムが含まれている可能性がありSomeOtherTypeます。私のせいですが、言語もコンパイラも明示的なヒント/警告を提供しませんでした。これはC#では非常に珍しいことです...

4

3 に答える 3

24

ジェネリックスの前を思い出してください...foreachあなたが次のような賢明なことをすることができるようにキャストしなければなりませんでした:

foreach (string x in names)
{
    // ...
}

それ以外の:

foreach (object tmp in names)
{
    string x = (string) tmp;
    // ...
}

後者はただ厄介です、IMO。暗黙のキャストを提供することは、他の言語とは異なりますが、ほとんどの場合、はるかに使いやすくなります。

C#に最初からジェネリックスと拡張メソッドがあった場合(使用できるようOfTypeCastforeach、まったく同じ方法で指定されなかったと思います。

にはさらに奇妙な点があることに注意してくださいforeach:型はまったく実装する必要はありませんIEnumerableGetEnumerator何かを返すメソッドがあり、それがMoveNext()とを持っている限りCurrent、C#コンパイラは問題ありません。これは、ジェネリックスの前に(ボクシングを避けるために)「強く型付けされたイテレーター」を実装できることを意味しました。

于 2009-06-04T10:53:12.387 に答える
9

C# 3 ではvarを使用しているため、コンパイラの警告が表示されます。

于 2009-06-04T10:48:25.080 に答える
4

foreachは、object型のオブジェクトを返すIEnumerableで機能します。すべてのアイテムについて、オブジェクトは指定したタイプにキャストされます。

C#3.0でvarを使用しない限り。次に、IEnumerable<T>コレクションによって実装されている場合、タイプはから取得されます。

于 2009-06-04T10:51:11.267 に答える