Foreach 可以抛出 InvalidCastException 吗?

发布于 2024-07-22 06:32:10 字数 599 浏览 8 评论 0原文

想象一下下面的代码:

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我问的原因是我的项目中的类似代码中有一个错误,我曾经在其中迭代来自外部库的自定义集合,其名称类似于SomeTypeCollection,但在fact 提供了基本类型项的集合,并且可能包含 SomeOtherType 的项。 我的错,但语言和编译器仍然没有提供任何明确的提示/警告,这对于 C# 来说是很不寻常的......

Imagine the following code:

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

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

I wonder, why is this foreach behavior so... not C#-like?
What happens here is an implicit cast to a subclass, which is error-prone and seems to be banned in every other place in the language. Or am I not right?

P.S. The reason I'm asking is that I had a bug in the similar code in my project, where I used to iterate through a custom Collection from an external library, which was called like SomeTypeCollection, but in fact provided a collection of base type items and could have contained items of SomeOtherType. My fault, but still neither the language, nor the compiler provided any explicit hints/warnings, which is quite unusual for C#...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苍白女子 2024-07-29 06:32:10

回想一下泛型之前... foreach 必须进行强制转换,以便您可以做一些明智的事情,例如:

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

而不是:

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

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

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

请注意,foreach 中还有更多奇怪之处:该类型根本不必实现 IEnumerable。 只要它有一个 GetEnumerator 方法,该方法返回的内容又包含 MoveNext()Current,C# 编译器就很高兴。 这意味着您可以在泛型之前实现“强类型迭代器”(以避免装箱)。

Think back to before generics... foreach had to cast so that you could do sensible things like:

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

instead of:

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

The latter is just icky, IMO. Providing an implicit cast is unlike the rest of the language, but makes it much easier to use in the vast majority of cases.

I suspect that if C# had had generics and extension methods to start with (so we could use OfType and Cast) that foreach wouldn't be specified in quite the same way.

Note that there's even more oddness in foreach: the type doesn't have to implement IEnumerable at all. So long as it has a GetEnumerator method which returns something which in turn has MoveNext() and Current, the C# compiler is happy. This meant you could implement a "strongly typed iterator" (to avoid boxing) before generics.

菩提树下叶撕阳。 2024-07-29 06:32:10

在 C# 3 中,我使用 var - 所以我收到编译器警告。

With C# 3 I'm using var - so I get the compiler warnings.

国产ˉ祖宗 2024-07-29 06:32:10

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

除非你在C# 3.0中使用var。 然后,如果该类型是由集合实现的,则将从 IEnumerable 中获取该类型。

foreach works on IEnumerable, which returns objects of type object. For every item, the object will be cast to the type you provided.

Unless you use var in C# 3.0. Then the type will be taken from IEnumerable<T>, if it is implemented by the collection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文