到 ToList() 还是不到 ToList()?
To ToList() or not to ToList()?
给定 在内存中 (不是 LINQ to SQL)类 列表:
List<MyClass> myItems = /*lots and lots of items*/;
我正在使用 GroupBy()
语句对其进行分组:
myItems.GroupBy(g => g.Ref)
然后立即在 foreach
循环中消耗在 "group" 上调用 .ToList()
有什么区别还是我应该只使用 IEnumerable
.
如此完整的代码示例:
和ToList()
List<List<MyClass>> groupedItemsA = new List<List<MyClass>>();
List<List<MyClass>> groupedItemsB = new List<List<MyClass>>();
List<MyClass> myItems = /*lots and lots of items*/;
List<IGrouping<string, MyClass>> groupedItems = myItems.GroupBy(g => g.Ref).ToList();
foreach(IGrouping<string, MyClass> item in groupedItems)
{
if (/*check something*/)
{
groupedItemsA.Add(item.ToList());
}
else
{
groupedItemsB.Add(item.ToList());
}
}
或
使用IEnumerable
List<List<MyClass>> groupedItemsA = new List<List<MyClass>>();
List<List<MyClass>> groupedItemsB = new List<List<MyClass>>();
List<MyClass> myItems = /*lots and lots of items*/;
IEnumerable<IGrouping<string, MyClass>> groupedItems = myItems.GroupBy(g => g.Ref);
foreach(IGrouping<string, MyClass> item in groupedItems)
{
if (/*check something*/)
{
groupedItemsA.Add(item.ToList());
}
else
{
groupedItemsB.Add(item.ToList());
}
}
这些"under the hood"的执行计划有什么区别吗?这两种方法会更有效还是真的无关紧要?
之后我不使用groupedItems
列表。
Is there any difference?
是,.ToList()
通过迭代分组集合创建一个新列表:
这是否明显应该由您进行基准测试。
如果你只迭代一次分组集合,.ToList()
这一步是不必要的,而且会比直接枚举GroupBy()
结果相对慢一些。
如果你确定你将只使用groupedItems
一次,那么使用.ToList()
有一个单一优势:如果在分组期间出现异常(例如,因为您的代码在计算 .Ref
时做了一些有趣的事情),异常将出现在 .ToList()
行中,而不是在 [=15] 行中=]...我不认为这是一个很大的优势(也许是一个劣势)。
澄清一下:
public class MyClass
{
public string Ref
{
get
{
// sometimes I like to throw an exception!
if (DateTime.Now.Ticks % 10 == 0) throw new Exception();
return "Foo";
}
}
}
请注意,您已明确将此问题标记为 IEnumerable
,并且在您的示例中 myItems
是 List<>
,因此我不会讨论 [=] 的区别19=] 或当您通过实体 Framework/Linq 到 SQL.
从数据库读取数据时
是的,有区别,而且可能很重要。
ToList()
将迭代并将每个迭代项追加到新列表中。这具有创建消耗内存的临时列表的效果。
有时您可能想要承受内存损失,尤其是当您打算多次迭代列表并且原始列表不在内存中时。
在您使用 ToList()
的特定示例中,您实际上最终迭代了两次 - 一次是构建列表,第二次是在您的 foreach 中。根据列表的大小和您的应用程序,这可能是也可能不是问题。
如果您每次枚举时都使用 IEnumerable
而不是 List()
,则 GroupBy
表达式将根据您的 myItems
列表重新求值.
这意味着如果您将另一个项目添加到 myItems
然后枚举它,该项目将包含在 GroupBy
表达式中。
当您调用 ToList
时,您会创建一个新列表,并且对 myItems
的任何更改都不会包含在 groupedItems
中。
给定 在内存中 (不是 LINQ to SQL)类 列表:
List<MyClass> myItems = /*lots and lots of items*/;
我正在使用 GroupBy()
语句对其进行分组:
myItems.GroupBy(g => g.Ref)
然后立即在 foreach
循环中消耗在 "group" 上调用 .ToList()
有什么区别还是我应该只使用 IEnumerable
.
如此完整的代码示例:
和ToList()
List<List<MyClass>> groupedItemsA = new List<List<MyClass>>();
List<List<MyClass>> groupedItemsB = new List<List<MyClass>>();
List<MyClass> myItems = /*lots and lots of items*/;
List<IGrouping<string, MyClass>> groupedItems = myItems.GroupBy(g => g.Ref).ToList();
foreach(IGrouping<string, MyClass> item in groupedItems)
{
if (/*check something*/)
{
groupedItemsA.Add(item.ToList());
}
else
{
groupedItemsB.Add(item.ToList());
}
}
或
使用IEnumerable
List<List<MyClass>> groupedItemsA = new List<List<MyClass>>();
List<List<MyClass>> groupedItemsB = new List<List<MyClass>>();
List<MyClass> myItems = /*lots and lots of items*/;
IEnumerable<IGrouping<string, MyClass>> groupedItems = myItems.GroupBy(g => g.Ref);
foreach(IGrouping<string, MyClass> item in groupedItems)
{
if (/*check something*/)
{
groupedItemsA.Add(item.ToList());
}
else
{
groupedItemsB.Add(item.ToList());
}
}
这些"under the hood"的执行计划有什么区别吗?这两种方法会更有效还是真的无关紧要?
之后我不使用groupedItems
列表。
Is there any difference?
是,.ToList()
通过迭代分组集合创建一个新列表:
这是否明显应该由您进行基准测试。
如果你只迭代一次分组集合,.ToList()
这一步是不必要的,而且会比直接枚举GroupBy()
结果相对慢一些。
如果你确定你将只使用groupedItems
一次,那么使用.ToList()
有一个单一优势:如果在分组期间出现异常(例如,因为您的代码在计算 .Ref
时做了一些有趣的事情),异常将出现在 .ToList()
行中,而不是在 [=15] 行中=]...我不认为这是一个很大的优势(也许是一个劣势)。
澄清一下:
public class MyClass
{
public string Ref
{
get
{
// sometimes I like to throw an exception!
if (DateTime.Now.Ticks % 10 == 0) throw new Exception();
return "Foo";
}
}
}
请注意,您已明确将此问题标记为 IEnumerable
,并且在您的示例中 myItems
是 List<>
,因此我不会讨论 [=] 的区别19=] 或当您通过实体 Framework/Linq 到 SQL.
是的,有区别,而且可能很重要。
ToList()
将迭代并将每个迭代项追加到新列表中。这具有创建消耗内存的临时列表的效果。
有时您可能想要承受内存损失,尤其是当您打算多次迭代列表并且原始列表不在内存中时。
在您使用 ToList()
的特定示例中,您实际上最终迭代了两次 - 一次是构建列表,第二次是在您的 foreach 中。根据列表的大小和您的应用程序,这可能是也可能不是问题。
如果您每次枚举时都使用 IEnumerable
而不是 List()
,则 GroupBy
表达式将根据您的 myItems
列表重新求值.
这意味着如果您将另一个项目添加到 myItems
然后枚举它,该项目将包含在 GroupBy
表达式中。
当您调用 ToList
时,您会创建一个新列表,并且对 myItems
的任何更改都不会包含在 groupedItems
中。