IEnumerable作为方法参数 [英] IEnumerable as method parameter

查看:68
本文介绍了IEnumerable作为方法参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我对IEnumerable t有几个一般性的问题.我知道它使用延迟执行,即仅在需要时才执行.我不知道什么时候最好使用IEnumerable< t>.作为方法参数.

假设我有一个从xml文件读取并返回IEnumerable t的方法,其中T是代表从文件读取的数据的类型.如果我将该数据作为IEnumerable传递(作为其他方法的输入参数),则仅在需要时才执行查询.使用IEnumerable t因为方法参数具有附加的优点,所以该方法也可以与List< t>一起使用.或T []数组,并且被调用的方法必须将类型强制转换为其他类型才能更改集合.不利的一面是,该查询将被多次执行,并且始终返回相同的结果,因为文件不会更改.我不太了解的另一件事是,当我调用接收IEnumerable< t>的方法时会发生什么.带有List< t>然后该方法将迭代列表.由于该方法是使用list调用的,因此没有任何查询要执行,因此(性能虎钳)与该方法将接收List一样.

我知道我没有在上面的文本中提出很多具体的问题,所以我不能期望得到具体的答案,但是也许有人可以解释关于上述主题的最佳实践是什么.

Uroš

Hi
I have a few general questions about IEnumerable<t>. I know that it uses deferred execution i.e. it is only executed when it needs to be. What I don''t know is when is best to use IEnumerable<t> as a method parameter.

Let say I have a method that reads from an xml file and returns an IEnumerable<t>, where T is the type representing the data read from the file. If I pass that data around(as input parameter for other methods), as IEnumerable, the query will be executed only when it needs to be. Using IEnumerable<t> as method parameter has an added plus that the method can also work with List<t> or T[] array and that the called method cannot change the collection without type casting it to something else. On the down side the query will be executed multiple times and always return the same results since the file does not change. Another thing I don''t quite get is what happens when i call a method that receives an IEnumerable<t> with a List<t> and that method iterates the list. Since the method was called with list, there isn''t any query to be executed, so is that (performance vise) the same as if the method would receive a List.

I know i haven''t ask many concrete questions in the text above, so I can not expect concrete answers, but maybe somebody can explains what are the best practices regarding the topic described above.

Uroš

推荐答案

开发实现System.Collections.IEnumerablehttp://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx [ http://msdn.microsoft.com/en-us/library/ttw7t8t6%28v = vs.110%29.aspx [ ^ ],
http://msdn.microsoft.com/en-us/library/9yb8xew9.aspx [ ^ ].

如果不需要它,则不必实现此接口.这对您来说是一个有趣的示例.尽管有关键字"enum" ,. NET枚举类型并不通过那些声明的(静态)类型成员来实现枚举.要使用foreach,您需要遍历其值(例如),但是通常情况下,这并不完全相同.为了介绍遍历这些成员的foreach(没有其他内容),我创建了一个单独的泛型类型,使用用户的枚举类型作为泛型参数.此泛型类型提供此枚举类型的全面信息,并通过实现System.Collections.IEnumerable启用foreach,如文章中所述:
​​枚举类型不枚举!解决.NET和语言限制 [ ^ ].

它可以使您对该接口的实用工具有一个非常一般的了解,您可以将其应用于代表任何任意数据集的各种数据结构.



作为方法参数?与接口类型参数一样,从实现中抽象出来是一件好事.具有此类参数的方法将能够遍历可通过forarch访问的集合,并访问该集合中的每个元素.在很多情况下,这都是重要的事情.

这个想法不限于参数传递.这只是基于抽象的通用方法.如果相关性太强的对象相互依赖,或者一个对象又相互依赖,则依赖对象可能需要指向另一个对象的引用成员.根据依赖的目的,引用经常不需要是类或结构类型,因为应该只公开功能的一小部分.在这种情况下,接口非常方便.



foreach的性能几乎完全取决于System.Collections.IEnumerator的实现性能.如您所见,IEnumerable的唯一作用是提供对IEnumerator的引用的访问权限,这将完成主要工作:
http://msdn.microsoft.com/en-us/library/system. collections.ienumerable.getenumerator.aspx [ ^ ],
http://msdn.microsoft.com/en-us/library/system.collections. ienumerator.aspx [ ^ ].

几乎所有内容都取决于IEnumerator.CurrentIEnumerator.MoveNext的实现.这些方法可以像索引(在数组或System.Collections.Generic.List中)那样非常简单的方式访问集合中的元素,但是它们还可以执行复杂的计算,查询某些内容等.甚至对要返回的元素的引用也可能不可用.立即,因此该算法会即时计算出所需的对象.如果听起来不明智,但在某些情况下这是有道理的.您需要了解每种实现方式会发生什么.

其实,我想给你另一个建议.并非总是可以相信自己对性能的判断.为了获得一些经验并更好地了解性能,您可以简化一些操作的时间.最准确的工具,它是 System.Diagnostics.Stopwatch类.

但是,.NET(CLI)有一个问题.您需要考虑到JIT花费的时间.通常,代码是按方法JIT编译的.因此,通常在过程生命周期中第一次调用某个方法时,该方法通常是JIT编译的.注意不要在计时中包括第一个电话.请参阅:
http://en.wikipedia.org/wiki/Just-in-time_compilation [ ^ ],
http://msdn.microsoft.com/en-us/magazine/cc163791.aspx [ ^ ],
http://msdn.microsoft.com/en-us/library/k5532s8a.aspx [ ^ ].

如果您在某个时间安排时间,某些结果将使您感到惊讶.但是,您不应该过多地参与此活动:仅需要获得一些想法并揭示瓶颈即可.通常瓶颈很少.大多数性能问题与通用代码设计方式有关,而不仅仅是与详细的实现细节有关.

—SA
The main reason to develop any type implementing System.Collections.IEnumerable, http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx[^], is to introduce the possibility of traversing some set of objects through forеаch statement:
http://msdn.microsoft.com/en-us/library/ttw7t8t6%28v=vs.110%29.aspx[^],
http://msdn.microsoft.com/en-us/library/9yb8xew9.aspx[^].

If you don''t need this, you don''t have to implement this interface. This is an interesting example for you. Despite of the keyword "enum", .NET enumeration type do not implement enumeration through those declared (static) type members. To use foreach, you would need to iterate through its values (for example), but in general case, this is not exactly the same. To introduce foreach traversing those members (not anything else), I created a separate generic type using user''s enumeration type as a generic parameter. This generic type provides comprehensive information of this enumeration type and enables foreach through the implementation of System.Collections.IEnumerable, as explained in the article:
Enumeration Types do not Enumerate! Working around .NET and Language Limitations[^].

It can give you a very general idea of the utility of this interface you could be able to apply to a wide range of data structures representing any arbitrary data sets.



As a method parameter? As always with interface-type parameters, this is good to abstract out from the implementation. The method with such parameter will be able to traverse through the set accessible via forarch and access each element in this set. In many cases, this is all what matters.

This idea is not limited to parameter passing. This is just the general approach based on abstraction. If too related objects depend on each other, or one depends on another, the depending object may need a reference member pointing to another object. Depending on the purpose of dependency, very often, the reference does not need to be a class or structure type, because only small part of functionality should be exposed. In this case, interfaces come very handy.



Performance of foreach is almost totally depends on the performance of the implementation of System.Collections.IEnumerator. As you can see, the only role of IEnumerable is to provide an access to the reference to IEnumerator which makes the major job:
http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator.aspx[^],
http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx[^].

Almost everything depends on what the implementation of IEnumerator.Current and IEnumerator.MoveNext do. These method can access the elements of the set in a very simple way like indexing (in arrays or System.Collections.Generic.List, but they can also perform complex calculations, query something, etc. Even the reference to the element to be returned might not be available immediately, so the algorithm calculates out the required object on the fly. If sounds not wise, but there are certain cases when this makes sense. You need to understand what happens in each implementation.

Actually, I would like to give you another advice. Not always you can trust your own judgement on performance. To gain some experience and get better idea on performance, you can simple time some operations. The most accurate tool for that it the class System.Diagnostics.Stopwatch.

There is one catch specific to .NET (CLI) though. You need to take into account the time taken by JIT. Most usually, the code is JIT-compiled on per-method basis. So, the method is usually JIT-compiled when a method is about to be called for the very first time in the process life time. Be careful not to include the first call in timing. Please see:
http://en.wikipedia.org/wiki/Just-in-time_compilation[^],
http://msdn.microsoft.com/en-us/magazine/cc163791.aspx[^],
http://msdn.microsoft.com/en-us/library/k5532s8a.aspx[^].

If you time things sometime, some results will come at surprise to you. However, you should not get into this activity too much: it is needed only to get some idea and to reveal the bottlenecks. There are usually to few bottlenecks. Most performance issues are related to general code design way more than to fine implementation detail.

—SA


这篇关于IEnumerable作为方法参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆