C# 我应该总是返回 IEnumerable<T> 而不是 IList<T> 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1072614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should I always return IEnumerable<T> instead of IList<T>?
提问by KingNestor
When I'm writing my DAL or other code that returns a set of items, should I always make my return statement:
当我编写返回一组项目的 DAL 或其他代码时,我是否应该始终使用 return 语句:
public IEnumerable<FooBar> GetRecentItems()
or
或者
public IList<FooBar> GetRecentItems()
Currently, in my code I have been trying to use IEnumerable as much as possible but I'm not sure if this is best practice? It seemed right because I was returning the most generic datatype while still being descriptive of what it does, but perhaps this isn't correct to do.
目前,在我的代码中,我一直在尝试尽可能多地使用 IEnumerable,但我不确定这是否是最佳实践?这似乎是正确的,因为我正在返回最通用的数据类型,同时仍在描述它的作用,但也许这样做是不正确的。
采纳答案by Jon Limjap
It really depends on why you are using that specific interface.
这实际上取决于您使用该特定界面的原因。
For example, IList<T>
has several methods that aren't present in IEnumerable<T>
:
例如,IList<T>
有几个方法不存在于IEnumerable<T>
:
IndexOf(T item)
Insert(int index, T item)
RemoveAt(int index)
IndexOf(T item)
Insert(int index, T item)
RemoveAt(int index)
and Properties:
和属性:
T this[int index] { get; set; }
T this[int index] { get; set; }
If you need these methods in any way, then by all means return IList<T>
.
如果您以任何方式需要这些方法,那么一定要 return IList<T>
。
Also, if the method that consumes your IEnumerable<T>
result is expecting an IList<T>
, it will save the CLR from considering any conversions required, thus optimizing the compiled code.
此外,如果使用您的IEnumerable<T>
结果的方法需要一个IList<T>
,它将使 CLR 免于考虑任何所需的转换,从而优化已编译的代码。
回答by Stuart
I think you can use either, but each has a use. Basically List
is IEnumerable
but you have count functionality, Add element, remove element
我认为你可以使用任何一个,但每个都有一个用途。基本上List
是,IEnumerable
但你有计数功能,添加元素,删除元素
IEnumerable
is not efficient for counting elements, or getting a specific element in the collection.
IEnumerable
对于计算元素或获取集合中的特定元素效率不高。
List
is a collection which is ideally suited to finding specific elements, easy to add elements, or remove them.
List
是一个非常适合查找特定元素、易于添加或删除元素的集合。
Generally I try to use List
where possible as this gives me more flexibility.
通常我会尽量使用List
,因为这给了我更大的灵活性。
Use
List<FooBar> getRecentItems()
rather than
IList<FooBar> GetRecentItems()
使用
List<FooBar> getRecentItems()
而不是
IList<FooBar> GetRecentItems()
回答by Alex Martelli
List<T>
offers the calling code many more features, such as modifying the returned object and access by index. So the question boils down to: in your application's specific use case, do you WANT to support such uses (presumably by returning a freshly constructed collection!), for the caller's convenience -- or do you want speed for the simple case when all the caller needs is to loop through the collection and you can safely return a reference to a real underlying collection without fearing this will get it erroneously changed, etc?
List<T>
为调用代码提供了更多功能,例如修改返回的对象和通过索引访问。所以问题归结为:在您的应用程序的特定用例中,您是否想要支持这样的使用(大概是通过返回一个新构造的集合!),为了调用者的方便 - 或者当所有的简单情况下您想要速度调用者需要循环遍历集合,您可以安全地返回对真正底层集合的引用,而不必担心这会导致它被错误地更改,等等?
Only you can answer this question, and only by understanding well what your callers will want to do with the return value, and how important performance is here (how big are the collections you would be copying, how likely is this to be a bottleneck, etc).
只有您才能回答这个问题,并且只有通过充分了解您的调用者想要对返回值做什么,以及性能在这里有多重要(您将复制的集合有多大,这有多大可能成为瓶颈,等等)。
回答by JP Alioto
It's not so simple when you are talking about return values instead of input parameters. When it's an input parameter, you know exactly what you need to do. So, if you need to be able to iterate over the collection, you take an IEnumberable whereas if you need to add or remove, you take an IList.
当您谈论返回值而不是输入参数时,这并不是那么简单。当它是一个输入参数时,您确切地知道您需要做什么。因此,如果您需要能够遍历集合,则使用 IEnumberable,而如果您需要添加或删除,则使用 IList。
In the case of a return value, it's tougher. What does your caller expect? If you return an IEnumerable, then he will not know a priori that he can make an IList out of it. But, if you return an IList, he will know that he can iterate over it. So, you have to take into account what your caller is going to do with the data. The functionality that your caller needs/expects is what should govern when making the decision on what to return.
在返回值的情况下,它更难。您的来电者期望什么?如果您返回一个 IEnumerable,那么他将不会先验地知道他可以从中制作一个 IList。但是,如果你返回一个 IList,他就会知道他可以迭代它。因此,您必须考虑您的调用者将如何处理数据。您的调用者需要/期望的功能是在决定返回什么时应该支配的。
回答by jerryjvl
That depends...
那要看...
Returning the least derived type (IEnumerable
) will leave you the most leeway to change the underlying implementation down the track.
返回最少派生类型 ( IEnumerable
) 将使您有最大的余地来更改底层实现。
Returning a more derived type (IList
) provides the users of your API with more operations on the result.
返回一个更派生的类型 ( IList
) 为您的 API 用户提供了对结果的更多操作。
I would always suggest returning the least derived type that has all the operations your users are going to need... so basically, you first have to deremine what operations on the result make sense in the context of the API you are defining.
我总是建议返回具有您的用户将需要的所有操作的最少派生类型......所以基本上,您首先必须确定在您定义的 API 的上下文中对结果进行的哪些操作是有意义的。
回答by Usman Masood
as all have said it depends, if you don't want Add/Remove functioanlity at calling layer then i will vote for IEnumerable as it provides only iteration and basic functionality which in design prespective i like. Returning IList my votes are always againist it but it's mainly what you like and what not. in performance terms i think they are more of same.
正如所有人所说,这取决于,如果您不想在调用层添加/删除功能,那么我将投票支持 IEnumerable,因为它仅提供我喜欢的设计方面的迭代和基本功能。返回 IList 我的投票总是反对它,但这主要是你喜欢什么,不喜欢什么。在性能方面,我认为它们更相似。
回答by Joel Mueller
One thing to consider is that if you're using a deferred-execution LINQ statement to generate your IEnumerable<T>
, calling .ToList()
before you return from your method means that your items may be iterated twice - once to create the List, and once when the caller loops through, filters, or transforms your return value. When practical, I like to avoid converting the results of LINQ-to-Objects to a concrete List or Dictionary until I have to. If my caller needs a List, that's a single easy method call away - I don't need to make that decision for them, and that makes my code slightly more efficient in the cases where the caller is just doing a foreach.
需要考虑的一件事是,如果您使用延迟执行 LINQ 语句来生成您的IEnumerable<T>
,则.ToList()
在从您的方法返回之前调用意味着您的项目可能会被迭代两次 - 一次是创建 List,一次是在调用者循环时、过滤或转换您的返回值。在可行的情况下,我喜欢避免将 LINQ-to-Objects 的结果转换为具体的列表或字典,除非我必须这样做。如果我的调用者需要一个 List,那么这是一个简单的方法调用——我不需要为他们做出这个决定,这使得我的代码在调用者只是执行 foreach 的情况下稍微更高效。
回答by Joel Mueller
I think you can use either, but each has a use. Basically
List
isIEnumerable
but you have count functionality, add element, remove elementIEnumerable is not efficient for counting elements
我认为你可以使用任何一个,但每个都有一个用途。基本上
List
是,IEnumerable
但你有计数功能,添加元素,删除元素IEnumerable 对于元素计数效率不高
If the collection is intended to be readonly, or the modification of the collection is controlled by the Parent
then returning an IList
just for Count
is not a good idea.
如果集合是只读的,或者集合的修改由 控制,Parent
则返回一个IList
just forCount
不是一个好主意。
In Linq, there is a Count()
extension method on IEnumerable<T>
which inside the CLR will shortcut to .Count
if the underlying type is of IList
, so performance difference is negligible.
在 Linq 中,有一个Count()
扩展方法IEnumerable<T>
,.Count
如果底层类型是 ,则 CLR 内部将快捷方式到该方法IList
,因此性能差异可以忽略不计。
Generally I feel (opinion) it is better practice to return IEnumerable where possible, if you need to do additions then add these methods to the parent class, otherwise the consumer is then managing the collection within Model which violates the principles, e.g. manufacturer.Models.Add(model)
violates law of demeter. Of course these are just guidelines and not hard and fast rules, but until you have full grasps of applicability, following blindly is better than not following at all.
一般来说,我觉得(意见)最好在可能的情况下返回 IEnumerable,如果您需要进行添加,则将这些方法添加到父类中,否则消费者将在 Model 中管理违反原则的集合,例如manufacturer.Models.Add(model)
违反法律德米特。当然,这些只是指导方针,并不是硬性规定,但在你完全掌握适用性之前,盲目遵循总比不遵循要好。
public interface IManufacturer
{
IEnumerable<Model> Models {get;}
void AddModel(Model model);
}
(Note: If using nNHibernate you might need to map to private IList using different accessors.)
(注意:如果使用 nNHibernate,您可能需要使用不同的访问器映射到私有 IList。)
回答by arbiter
If you do not counting in your external code it is always better to return IEnumerable, because later you can change your implementation (without external code impact), for example, for yield iteratorlogic and conserve memory resources (very good language feature by the way).
如果您不计入外部代码,返回 IEnumerable 总是更好,因为稍后您可以更改您的实现(不受外部代码影响),例如,用于yield 迭代器逻辑并节省内存资源(顺便说一句,非常好的语言功能)。
However if you need items count, don't forget that there is another layer between IEnumerable and IList - ICollection.
但是,如果您需要项目计数,请不要忘记 IEnumerable 和 IList - ICollection之间还有另一层。
回答by Tiberiu Ana
I might be a bit off here, seeing that no one else suggested it so far, but why don't you return an (I)Collection<T>
?
我可能有点不对劲,看到到目前为止没有其他人建议它,但你为什么不返回一个(I)Collection<T>
?
From what I remember, Collection<T>
was the preferred return type over List<T>
because it abstracts away the implementation. They all implement IEnumerable
, but that sounds to me a bit too low-level for the job.
据我所知,Collection<T>
是首选的返回类型,List<T>
因为它抽象了实现。他们都实现了IEnumerable
,但这对我来说听起来有点太低级了。