我应该喜欢IEnumerable <T>还是Arrays?

Ale*_*fie 29 .net c# vb.net design-principles

在我工作的许多项目中,每当我必须返回一个只读集合时,我使用该IEnumerable<T>接口并使其类型特定如下:

Public ReadOnly Property GetValues() As IEnumerable(Of Integer)
    Get
        'code to return the values'
    End Get
End Property
Run Code Online (Sandbox Code Playgroud)

大多数时候,我返回一个List但是在一些函数和只读属性中我返回一个数组,这个数组也可以通过扩展方法的礼貌来达到目的.

我的问题是我会通过返回违反任何设计原则IEnumerable<T>s,而不是特定类型(例如:List<T>,HashSet<T>,Stack<T>ArrayS)

Dav*_*vid 34

我通常也喜欢IEnumerable<T>.主要的是问自己从方法返回的实际(甚至是最小)功能(或者在方法参数的情况下传递给它).

如果你需要做的只是对结果集进行枚举,那么IEnumerable<T>就完全如此.不多也不少.这使您可以灵活地在某些情况下返回更多特定类型,如果需要,而不会破坏方法的足迹.

  • 这与数组相比没有风险,因为"IEnumerable"可能隐藏了一些执行以访问元素,而`[]`永远不会?即.延期执行的潜在副作用是否有点超过了收益? (10认同)
  • 数组在其索引器上也有代码 (2认同)

Dom*_*nic 17

大卫的回答几乎涵盖了它; IEnumerable<T>一般来说是最好的做法.您可以通过查看大多数较新的框架方法来看到这一点.

我只是想补充一点,因为你指定只读集合在你原来的问题,你可以通过调用执行这.ToList().AsReadOnly()在您IEnumerable<T>返回之前的实例.这将创建一个ReadOnlyCollection<T>让您返回的具体实例.您的返回类型仍然是IEnumerable<T>,因为呼叫者不需要知道您是专门返回的ReadOnlyCollection<T>,但是这样可以防止呼叫者在脚中射击.

(如果没有这个步骤,调用者可以尝试将IEnumerable<T>它从你的方法转换为List<T>.如果转换成功,那么如果这是你最初使用的那个,那么调用者可以修改你在里面操作的相同列表你的方法,可能会产生意想不到的后果.)


Joe*_*Joe 14

就个人而言,我认为IEnumerable<T>从API 返回是一个强烈暗示,实现可能会使用延迟评估.

知道可以使用延迟评估对于调用者来说可能很重要,因为它意味着:

  • 多次迭代结果(例如,获得计数然后访问数据)将导致评估不止一次.

  • 迭代结果时,可以从API抛出异常:

例如

IEnumerable<MyObject> LazyEvaluatedApi()
{
}

...

IEnumerable<MyObject> result = LazyEvaluatedApi();
... 
foreach(MyObject item in result) // Exception from LazyEvaluatedApi may be thrown here.
{
}
Run Code Online (Sandbox Code Playgroud)

如果您认为任何实现都不需要使用延迟评估(例如数据访问层API),我宁愿返回ICollection<T>IList<T>.除了让调用者访问Count属性(ICollection<T>IList<T>)和索引器(IList<T>仅限)之外,您还清楚地表明不会进行惰性求值.

返回你的ICollection<T>或者IList<T>,你的具体实现通常可能会返回一个List<T>.如果列表是只读的重要,那么返回List<T>.AsReadOnly()