Kla*_*sen 4 c# linq extension-methods
说我有一节课:
public class MyClass
{
...
}
Run Code Online (Sandbox Code Playgroud)
和一个返回的Web服务方法 IEnumerable<MyClass>
Web服务的使用者定义了一些方法:
public void DoSomething(MyClass myClass)
{
...
}
Run Code Online (Sandbox Code Playgroud)
现在,消费者可以DoSomething通过两种方式调用webservice方法的结果:
var result = // web service call
foreach(var myClass in result)
{
DoSomething(myClass);
}
Run Code Online (Sandbox Code Playgroud)
要么:
var result = // web service call
result.ToList().ForEach(DoSomething);
Run Code Online (Sandbox Code Playgroud)
毋庸置疑,我更喜欢第二种方式,因为它更短,更具表现力(一旦你习惯了我的语法).
现在,Web服务方法只公开一个IEnumerable<MyClass>,但它实际上返回一个List<MyClass>(AFAIK)意味着实际的序列化对象仍然是一个List<T>.但是,我发现(使用反射器)Linq方法ToList()制作了所有对象的副本,IEnumerable<T>而不管实际的运行时类型(在我看来,它可能只是将参数转换为a,List<T>如果它已经是一个).
这显然有一些性能开销,特别是对于大型列表(或大型对象列表).
那么我该怎么做才能克服这个问题,为什么ForEachLinq中没有方法呢?
顺便说一句,他的问题与这个问题含糊不清.
您可以编写扩展方法,但有充分的理由说明为什么没有实现ForEach IEnumerable<T>.第二个例子
result.ToList().ForEach(DoSomething);
Run Code Online (Sandbox Code Playgroud)
将IEnumerable复制到List中(除非它已经是List,我假设)所以你最好只用旧的迭代IEnumerable foreach(var r in result) {}.
附录:
对我来说,Eric Lippert的文章的关键点是添加ForEach没有任何好处,并增加了一些潜在的陷阱:
第二个原因是,这样做会增加语言的新代表性能力.这样做可以让你重写这个完全清晰的代码:
foreach(foo foo in foos){声明涉及foo; }
进入这段代码:
foos.ForEach((Foo foo)=> {声明涉及foo;});
它使用几乎完全相同的字符,顺序略有不同.然而第二个版本更难理解,更难调试,并引入了闭包语义,从而可能以微妙的方式改变对象的生命周期.
我更喜欢这个: -
foreach (var item in result.ToList())
{
DoSomething(item);
}
Run Code Online (Sandbox Code Playgroud)
它是一个更清晰的习语,它说收集一起列表的东西,然后做一些重要的事情,可能会改变应用程序的状态.它的旧学校,但它的工作,实际上更广泛的观众可以理解.