使用IEnumerable和List进行迭代

本文关键字:迭代 List IEnumerable 使用 | 更新日期: 2023-09-27 18:16:07

我刚刚在网上找到了一些c#代码重构的例子,偶然发现了这段特殊的代码。

谁能给我解释一下,为什么Method2()会比Method1()好?

方法#1 -对IEnumerable<string>进行多次迭代

public void Method1()
{
    IEnumerable<string> names = GetNames();
    foreach (var name in names)
    {
        Console.WriteLine("Found " + name);
    }
    var allnames = new StringBuilder();
    foreach (var name in names)
    {
        allnames.Append(name + " ");
    }
}

方法#2 -对List<string>进行多次迭代

public void Method2()
{
    IEnumerable<string> names = GetNames();
    var enumerable = names as List<string> ?? names.ToList();
    foreach (var name in enumerable)
    {
        Console.WriteLine("Found " + name);
    }
    var allnames = new StringBuilder();
    foreach (var name in enumerable)
    {
        allnames.Append(name + " ");
    }
}

使用IEnumerable和List进行迭代

因为IEnumerable可能做延迟迭代。在这种情况下,迭代代码将运行两次。

例如,如果GetNames实际上正在与DB通信,那么迭代返回的IEnumerable可能会执行实际的SQL查询。在这种情况下,在方法1中,您将执行该任务两次。

在方法2中,对ToList的调用只导致IEnumerable的求值一次,因此您的SQL查询只运行一次。

因为你并不总是知道IEnumerable的背后是什么,所以最好的做法是只强制枚举一次。

这两种方法都很好。唯一的区别是为什么我们应该使用其中一个。对于第二个方法,. tolist()调用急切地求值表达式,它准备IEnumerable集合。在第一个方法中,它只在CLR执行以下代码块时计算表达式。正如我所说,这取决于你想如何取得成功。

foreach (var name in names)

方法2更好,因为IEnumerable可能有多个枚举。