IEnumerable Where()和ToList()-它们实际上是做什么的? [英] IEnumerable Where() and ToList() - What do they really do?

查看:441
本文介绍了IEnumerable Where()和ToList()-它们实际上是做什么的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道Where()ToList()方法到底在做什么.具体来说,我想知道Where()是在内存中创建一个新对象还是返回一个新对象.

I was wondering what exactly the Where() and ToList() methods are doing. Specifically I was wondering if the Where() will create a new object in memory or return a new object.

好吧,看下面的代码,说我有一个骨架日志类.

Ok, looking at the following code, say I have a skeleton log class.

public class Log()
{
    public string Log {get;set;}
    public string CreatedByUserId {get;set;}
    public string ModifiedUserId {get;set;}
}

在我的业务逻辑中,说我只希望由某个用户创建或修改日志.这将通过方法FilterLogsAccordingToUserId().

In my business logic, say I only want logs created or modified by a certain user. This is going to be accomplished with a method: FilterLogsAccordingToUserId().

public IEnumerable<Log> FilterLogsAccordingToUserId(IEnumerable<Log> logs, string userId)
{
    int user = int.Parse(userId);
    return logs.Where(x => x.CreatedByUserId.Equals(user) ||
                           x.ModifiedByUserId.Equals(user)).ToList();
}

在这种情况下,Where()是通过删除所有不符合条件的对象来修改IEnumerable<Log>,还是捕获所有对象,将该对象转换为内存中的列表,然后返回该新对象?

In this situation, is Where() modifying the IEnumerable<Log> by removing all objects that don't match the condition, or is it grabbing all objects, casting that object to a list in memory, and then return that new object?

如果是第二种可能性,是否有足够的日志列表传递给函数,我是否应该担心性能?

If it is the second possibility, am I right to be concerned about performance if a sufficiently large list of logs is passed to the function?

推荐答案

让我们分别采用这两种方法.

Let's take the two methods separately.

这将返回一个新对象,该对象在枚举时将通过谓词过滤原始收集对象.

This one will return a new object, that when enumerated, will filter the original collection object by the predicate.

它绝不会更改原始集合,但会链接到它.

It will in no way change the original collection, but it will be linked to it.

它也是一个延迟执行集合,这意味着直到您真正枚举它,并且每次枚举,它都会使用原始集合并对它进行过滤.

It is also a deferred execution collection, which means that until you actually enumerated it, and every time you enumerate it, it will use the original collection and filter that.

这意味着,如果您更改原始集合,则其过滤结果将相应更改.

This means that if you change the original collection, the filtered result of it will change accordingly.

这是一个简单的 LINQPad 程序,该程序演示:

Here is a simple LINQPad program that demonstrates:

void Main()
{
    var original = new List<int>(new[] { 1, 2, 3, 4 });
    var filtered = original.Where(i => i > 2);
    original.Add(5);
    filtered.Dump();
    original.Add(6);
    filtered.Dump();
}

输出:

如您所见,在满足第二个集合的过滤条件的原始集合中添加更多元素也会使这些元素也出现在过滤后的集合中.

As you can see, adding more elements to the original collection that satisfies the filtering conditions of the second collection will make those elements appear in the filtered collection as well.

这将创建一个新的列表对象,将其填充到集合中,然后返回该集合.

This will create a new list object, populate it with the collection, and return that collection.

这是一种直接方法,这意味着一旦有了该列表,现在它便是与原始集合完全不同的列表.

This is an immediate method, meaning that once you have that list, it is now a completely separate list from the original collection.

请注意,该列表中的对象 可能仍与原始集合共享,ToList方法不会为所有这些对象创建新副本,而是集合是新的.

Note that the objects in that list may still be shared with the original collection, the ToList method does not make new copies of all of those, but the collection is a new one.

这是一个简单的 LINQPad 程序,该程序演示:

Here is a simple LINQPad program that demonstrates:

void Main()
{
    var original = new List<int>(new[] { 1, 2, 3, 4 });
    var filtered = original.Where(i => i > 2).ToList();
    original.Add(5);

    original.Dump();
    filtered.Dump();
}

输出:

在这里您可以看到,一旦我们创建了该列表,如果原始集合更改了,它就不会更改.

Here you can see that once we've created that list, it doesn't change if the original collection changes.

您可以认为Where方法是链接到原始集合,而ToList只会返回一个包含元素的新列表,而不会链接到原始集合.

You can think of the Where method as being linked to the original collection, whereas ToList will simply return a new list with the elements and not be linked to the original collection.

现在,让我们看看您的最后一个问题.您应该担心性能吗?嗯,这是一个相当大的话题,但是,您应该担心性能,但不要一直到如此程度.

Now, let's look at your final question. Should you be worried about performance? Well, this is a rather large topic, but yes, you should be worried about performance, but not to such a degree that you do it all the time.

如果您将 large 集合提供给Where调用,则每次枚举Where调用的结果时,都将枚举原始的大集合并对其进行过滤.如果过滤器仅允许其中的几个元素通过,则每次枚举时,它仍将在原始大型集合中枚举.

If you give a large collection to a Where call, every time you enumerate the results of the Where call, you will enumerate the original large collection and filter it. If the filter only allows for few of those elements to pass by it, it will still enumerate over the original large collection every time you enumerate it.

另一方面,对较大的内容执行ToList也会创建较大的列表.

On the other hand, doing a ToList on something large will also create a large list.

这会成为性能问题吗?

谁能说,但就性能而言,这是我的第一答案:

Who can tell, but for all things performance, here's my number 1 answer:

  1. 首先知道您有问题
  2. 第二步,使用适当的工具(内存,cpu时间等)测量代码,找出哪里性能问题
  3. 修复
  4. 返回数字1
  1. First know that you have a problem
  2. Secondly measure your code using the appropriate (memory, cpu time, etc.) tool to figure out where the performance problem is
  3. Fix it
  4. Return to number 1

您经常会看到程序员对一段代码感到烦恼,认为这会引起性能问题,而这只会被缓慢的用户看着屏幕想知道下一步该怎么做,或者被数据的下载时间所吓倒. ,或者将数据写入磁盘所需的时间,或者没有.

Too often you will see programmers fret over a piece of code, thinking it will incur a performance problem, only to be dwarfed by the slow user looking at the screen wondering what to do next, or by the download time of the data, or by the time it takes to write the data to disk, or what not.

首先您知道,然后解决.

First you know, then you fix.

这篇关于IEnumerable Where()和ToList()-它们实际上是做什么的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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