2012-09-20 34 views
3

我正在设计一个有几个函数返回对象列表的类。我注意到当我的IEnumerable<T>转换为List<T>时调试变得更容易,因为可以在监视窗口中查看对象。但是,我不确定这是否是IEnumerable的最佳做法。返回IEnumerable <T>或立即转换为列表<T>?

问:哪个更好?

public IEnumerable<MyData> GetData() 
{ 
    return Foo(); 
} 

public IEnumerable<MyData> GetData() 
{ 
    return Foo().ToList(); 
} 

回答

5

良好做法 - 除非有充分的理由/要求,否则不要做工作。所以除非你有特殊的理由 - 只需返回IEnumerable<MyData>而不用调用ToList()/ ToArray()就可以了。

可能的原因是:

  • 功能有望完成可能延迟枚举
  • 你期望的结果被列举的评价多次
+0

两个(好的)理由的一个小例子对理解非常有帮助。 – martinstoeckli

2

更好的回报IEnumerable<..>随着越来越多的泛型类型。在之后,主叫方可以决定如何处理它。在情况下返回在两种情况下IEnumerable<..>,所以没有任何理由运行ToLIst(),只是返回IEnumerable

+2

+0:良好的建议...对于另一个问题:)请注意,返回类型是相同的两个样本... –

+0

@AlexeiLevenkov:将重新回答,以适应问题 – Tigran

+0

+1编辑,也I认为“没有任何理由”是太强大了(我的答案中有一对)。 –

1

这真的取决于你的需求。方法签名的返回类型也是该方法合同的一部分。返回IEnumerable的方法表示一个值流,而返回List(或更抽象的Collection)的方法返回可变的值集合。

我通常会试着跟上以下做法。在当存在关于值的数量或其中加载所有值将花费相当长的时间/资源(例如查询结果)没有固定知识使用一个IEnumerable或的IObservable

  • 尝试和流数据。
  • 将数组用于预先已知的不应该可变的固定集合。
  • 对于可以突变的预先已知的固定集合使用ICollection。
+0

在这种情况下,该类建立数据库连接并让您从数据库中检索数据列表。我仍然怀疑:) – l33t

+0

我增加了一些最佳做法。在你的情况下,我会去IEnumerable,因为从数据库检索数据将需要一些时间,它不太可能的数量,如果数据是事先知道的 – Polity

1

如果您使用的是要处理的工作单元,我最好使用元素列表,因为一旦处置完毕,您将无法获取元素。

在所有其他情况下,它可以返回通用的IEnumerable,因为它提供了更好的灵活性。

最后,这一切都归结为您的要求,请注意,IEnumnerable不会在分配给变量的确切时刻检索元素,而是在枚举时检索元素。

+0

在这种情况下,数据从数据库(单身人士)检索本身是永远不会处置。 – l33t

+0

当然,当您使用实体框架或其他ORM并且实现工作模式单元时,我会引用这些案例。 – Freeman

+0

+1非常重要的一点。在正常情况下,返回不要调用ToList。但是当在外部作用域中使用可能会改变的东西(连接,关闭)时,您必须首先使用ToList。 – Sruly

0

返回的IEnumerable让来电者决定如何处理做结果 - 要么枚举它,要么将其传递给其他目录,而不在当前时刻枚举它。 ToList()强制将数据枚举到此处,然后传递给调用者。

因此-IEnumerable最有可能是两者中较好的一个 - 但是在调试时使用ToList会更容易。

+2

框架设计指南建议用最具体的类型来定义合约,而不是'IEnumerable'数组。由于FGD是内部类型,所以不要返回'List '。 Aray应该在您复制时返回,'Collection '当您保留对该集合的引用时(所以不得复制)。当然,这个准则是针对可重用的框架的,而不是针对LOB应用程序的。 – Steven

1

IEnumerable<T>是提供呼叫者T的集合的合同。然而,当您使用IList<T>List<T>,你所提出的建议,他们可以直接添加或删除元素(不通过任何方法,如添加或注册你可以去有你的班级实施)。如果您的意图仅仅是让调用者看到'项目',IEnumerable是更好的合同。

虽然它不是100%,但我将IEnumerable返回值视为只读集合。

易于调试应该是次要的好设计。我建议你简单地单元测试你的类,而不是依赖于能够在运行时偷看内部。但是,在大多数情况下,调试器将“基本”类显示为第一项。所以IEnumerable的第一个项目是你实际使用的List。它只需要再一次'扩大'就可以看到成员!

0

有一个简单的规则:返回更多concrette,接受更通用的。

如果您的返回值确实是IEnumerable<>,则按原样返回。但从来没有这样做:

public IEnumerable<MyData> GetData() 
{ 
    return this.list; // list = new List<MyData>(); 
} 

代码超过限制呼叫者没有任何需要。它将成为一个列表,并且调用者无论如何都能够将其列出并清除它。

相关问题