Foreach 可以抛出 InvalidCastException 吗?
想象一下下面的代码:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
回想一下泛型之前...
foreach
必须进行强制转换,以便您可以做一些明智的事情,例如:而不是:
后者只是令人讨厌,IMO。 提供隐式转换与语言的其他部分不同,但使其在绝大多数情况下更易于使用。
我怀疑如果C#有泛型和扩展方法来开始(所以我们可以使用
OfType
和Cast
),foreach
不会以完全相同的方式指定。请注意,
foreach
中还有更多奇怪之处:该类型根本不必实现IEnumerable
。 只要它有一个GetEnumerator
方法,该方法返回的内容又包含MoveNext()
和Current
,C# 编译器就很高兴。 这意味着您可以在泛型之前实现“强类型迭代器”(以避免装箱)。Think back to before generics...
foreach
had to cast so that you could do sensible things like:instead of:
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
andCast
) thatforeach
wouldn't be specified in quite the same way.Note that there's even more oddness in
foreach
: the type doesn't have to implementIEnumerable
at all. So long as it has aGetEnumerator
method which returns something which in turn hasMoveNext()
andCurrent
, the C# compiler is happy. This meant you could implement a "strongly typed iterator" (to avoid boxing) before generics.在 C# 3 中,我使用 var - 所以我收到编译器警告。
With C# 3 I'm using var - so I get the compiler warnings.
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.