用IEnumerable和List迭代

时间:2013-05-30 09:53:29

标签: c# list refactoring iteration ienumerable

我刚在互联网上发现了几个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 + " ");
    }
}

3 个答案:

答案 0 :(得分:4)

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

例如,如果GetNames实际上与数据库进行通信,则迭代返回的IEnumerable可能会执行实际的SQL查询。在方法1中的哪种情况下,您将执行该任务两次。

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

因为你并不总是知道IEnumerable背后的实际内容,所以通常只会强制枚举一次。

答案 1 :(得分:0)

这两种方法都很擅长。唯一的区别因素是为什么我们应该使用其中一个。在第二种方法的情况下,.ToList()调用急切地评估表达式,该表达式准备IEnumerable集合。在第一种方法中,它仅在CLR执行以下代码块时评估表达式。正如我所说,这取决于你想要如何领先。

foreach (var name in names)

答案 2 :(得分:0)

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