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;
    // ...
}

后者只是 icky,IMO。提供隐式转换与语言的其他部分不同,但在绝大多数情况下更容易使用。

怀疑如果 C# 有泛型扩展方法开始(所以我们可以使用OfTypeand Cast),那foreach将不会以完全相同的方式指定。

请注意,更奇怪的是foreach:类型根本不需要实现IEnumerable。只要它有一个GetEnumerator方法返回的东西又具有MoveNext()and Current,C# 编译器就会很高兴。这意味着您可以在泛型之前实现“强类型迭代器”(以避免装箱)。

于 2009-06-04T10:53:12.387 回答
9

对于 C# 3,我使用的是var - 所以我收到编译器警告。

于 2009-06-04T10:48:25.080 回答
4

foreach 适用于 IEnumerable,它返回 object 类型的对象。对于每个项目,对象将被转换为您提供的类型。

除非您在 C# 3.0 中使用var 。然后类型将取自IEnumerable<T>,如果它是由集合实现的。

于 2009-06-04T10:51:11.267 回答