2

我想知道以下事实。我有一个数据存储库,它返回我所有的IEnumerable<Customer>.

在我的业务逻辑中,有时我需要列表,以便我可以添加一些东西。

当我检索时,IEnumerable<Customer>我有 2 个选项可以从中获取列表。

像这样使用 Linq 扩展方法.ToList()或强制转换(我认为它不是转换)(List<Customer>)IEnumerable<Customer>

必须提到我不使用列表进行迭代,所以我不需要每次都使用我的枚举的新副本。在这种情况下,在我的简单情况下,我必须使用 cast 方法而不是.ToList(这会创建一个新副本)吗?

// use simple cast?
List<Customer> customers = (List<Customers>)DataSource.GetCustomers(); 

// or if i use this i get a bit of performance loss?
List<Customer> customers = DataSource.GetCustomers().ToList(); 
4

5 回答 5

5

我会选择ToList(),因为该方法返回 anIEnumerable<Customer>并且您无法确定内部实现。

也许现在GetCustomers()返回一个List<>被 an 掩蔽的IEnumerable<>,但是如果将来内部实现发生变化怎么办?

编辑 :

List<Customer>实现了 interface IEnumerable<Customer>,以及一个类似Customer[]或 a的数组LinkedList<Customer>。因此,当您收到一个类型的对象时,IEnumerable<WhateverClass>您不能确定它是 a List<Customer>,当然,只有当您要转换的类型在接口后面相同时,转换才有效,否则您将收到异常。

使用ToList(),正如您正确所说的,您创建了一个包含 元素的新对象IEnumerable<>,但至少您可以安全地迭代/修改该对象而没有任何异常。

方法返回IEnumerable<T>是因为通过这种方式它不会绑定到任何特定的集合实现,并且将来它可以从列表切换到数组或其他任何方式而不更改方法签名......

于 2012-07-28T12:20:11.250 回答
2

这取决于。如果大小很小,我会使用 .ToList(),但您必须了解这将复制列表。

如果它很大或者你做了很多(并且它会造成性能损失),你可以检查从 .GetCustomers() 返回的对象是否是一个列表,如果是 - 强制转换,否则使用 .ToList() 创建一个副本。

于 2012-07-28T12:25:49.547 回答
1

您可以通过使用条件来进行转换,以防止未来的实现更改。就像是

List<Customer> customers = null;
try
{
     customers = (List<Customers>)DataSource.GetCustomers();
}
catch
{
    customers = DataSource.GetCustomers().ToList();
}

这样,只要 IEnumerable 是一个列表,您就可以避免复制列表,但是如果将来由于某种原因内部实现发生更改,您的代码将继续工作。

于 2012-07-28T12:30:01.380 回答
1

我建议使用 .ToList()。它的性能会更差,但是如果您使用有关 API 实现细节的信息,并且您正在做出无根据的假设。明天有人会将 IEnumerable 更改为不是列表的内容,您的代码将开始抛出异常。

于 2012-07-28T12:21:09.503 回答
0

返回 IEnumerable 的存储库的全部意义在于它不能保证实际上是一个列表。(现在可能是,但使用 IEnumerable 允许以后更改实现)。

要么使用 .ToList() 方法,要么让存储库返回 List 或 IList。

于 2012-07-28T12:23:40.860 回答