C#、objectCollection.OfType() 和 foreach(objectCollection 中的 T 项)、IEnumerable 到 IEnumerable
我个人的编码风格属于 Enumerable.OfType
。我在任何地方都使用它,它有点意义。特别是 IEnumerable
允许强大的 linqToObject 功能。我讨厌 ObjectCollections 的“类型不安全”循环,例如下面的示例。现在我有一些关于循环这些“UnGenericCollections”的问题。
问题 1:如果我将此 ArrayList
转换为 Enumerable
与简单的 foreach/if-checks 相比,额外的循环有多大?
var ark = new ArrayList();
ark.Add(new Human());
ark.Add(new Human());
ark.Add(new Animal());
而不是:
foreach (object passenger in ark)
{
if (passanger is Human) { }
if (passanger is Animal) { }
}
我使用:
foreach (var human in ark.OfType<Human>())
{
}
foreach (var animal in ark.OfType<Animal>())
{
}
问题 2: 在 foreach 循环到不同类型的变量期间,将使用哪种强制转换/转换方式?这是一种语言功能还是开箱即用?
foreach (Human human in ark) { }
谢谢你忍受我糟糕的英语。最好的问候,本杰明
To my personal coding style belongs Enumerable.OfType<T>()
. I use it everywhere it makes a little bit of sense. Especially IEnumerable<T>
allows mighty linqToObject functionallity. I hate the "type-unsafe" looping of ObjectCollections such as the samples below. Now I have some questions about looping across these "UnGenericCollections".
ConfigurationSectionCollection
HttpModuleCollection
SPBaseCollection
SPFieldCollection
ArrayList
- so on...
Question 1: If I convert this ArrayList
to Enumerable<T>
how big is the additional loop in comparison with the simple foreach/if-checks?
var ark = new ArrayList();
ark.Add(new Human());
ark.Add(new Human());
ark.Add(new Animal());
Instead of:
foreach (object passenger in ark)
{
if (passanger is Human) { }
if (passanger is Animal) { }
}
I use:
foreach (var human in ark.OfType<Human>())
{
}
foreach (var animal in ark.OfType<Animal>())
{
}
Question 2: During a foreach loop into a different typed variable, which way of casting/converting will be used? Is this a language feature or does that work out of the box?
foreach (Human human in ark) { }
Thanks for enduring my awful English. Best regards,Benjamin
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Ans 1:
在您的示例中 - 您实际上可能会迭代 FULL 枚举两次。
Ans 2:
如果方舟中存在非人类,则会抛出 InvalidCastException 异常。
我个人更喜欢
ark.OfTypes()
,以防我知道我只想处理Human
和Animals
但会忽略精灵
。这样代码更加简洁,并且您在 foreach 循环中处理强类型对象。但同样,如果我不想忽略
Elves
,我宁愿迭代完整的 ArrayList 并使用强制转换。Ans 1:
In your sample - you may actually be iterating over the FULL enumerable twice.
Ans 2:
It would throw an InvalidCastException exception if there are any non-human in ark.
I would personally prefer
ark.OfTypes<T>()
, in case I know I only want to deal withHuman
andAnimals
but would be ignoringElves
. This way code is much more cleaner and you are dealing with strongly typed object in your foreach loop.But again in case I do not want to ignore
Elves
, I would take rather iterate thru full ArrayList and use casts.由于 ArrayList 实现了 IEnumerable,因此您不会发现任何差异。实际上,任何实现此接口的东西都可以在 foreach 语句中使用。
将构建转换对象而不是设置 var(因为它是显式转换),但如果枚举中有动物,则最终将不得不处理转换异常。
You'll find no difference since ArrayList implements IEnumerable. Actually, anything that implements this interface may be used in a foreach statement.
Casting the object instead of setting up a var will build (since it's an explicit cast) but if you have an animal inside the enumeration, you'll end up having to deal with casting exceptions.
为了防止集合被迭代两次并保持某种甜蜜的语法,我提供了一个扩展方法,允许链接指定类型的 foreach。
我觉得这会很有趣:
所以..现在如何让这件事变得不那么糟糕? :D
To prevent the collection from being iterated two times and to keep some kind of sweet syntax, I'd come with a extension method that allows chaining foreachs for specified types.
I thought it would be funny:
so.. now how to make this suck less? :D
Enumerable.OfType
将遍历所有元素并为您执行is T
检查。因此,每个OfType
调用都会迭代集合中的所有元素。那一定会慢一些。但如果它慢到你不应该在你的程序中这样做,那就是另一回事了。我认为将没有相同父级的类的对象放入一个集合中是否有意义。也许您可以找到一些抽象,然后在 foreach 中将所有对象强制转换为基类并使用多态调用。
Enumerable.OfType
will go over all elements and do theis T
check for You. So everyOfType
call will iterate over all elements in collection. That must be slower. But it's other thing if it's slower to the point You shouldn't do it in Your program.I would think If there is a point in putting objects of classes that don't have same parent in one collection. Maybe You could find some abstraction and then in foreach cast all objects to base class and use polymorphic calls.