可能重复:
Collection<T> versus List<T> what should you use on your interfaces?
考虑这个方法 - 返回的变量myVar
是List<T>
,但方法MyMethod()
的返回类型是IEnumerable<T>
:
public IEnumerable<T> MyMethod(string stuff)
{
var myVar = new List<T>();
//do stuff
return myVar;
}
基本上,我想知道的是,如果将myVar
作为其他类型返回就可以了。
具体来说,就我的情况而言,'do stuff'会通过DataRow
并将DataRow
中的项目分配给对象列表。我也有其他地方ICollection
和IList
返回类型的类似情况。
我想要返回IEnumerable
或ICollection
的原因是我不会返回超过需要的内容。但与此同时,如果需要,调用者可以将返回值转换为List
。
然而,我的return语句返回List
而不是方法的返回类型似乎很奇怪。这是正常做法吗?这样做有什么不对吗?
澄清(回应重复评论):
只是为了澄清一下,我很好奇的是,如果我的正文中的return语句返回List<T>
是可以的,但方法标题的返回类型为IEnumerable
,或者可能是ICollection
,Collection
等......某些与不同而非身体返回陈述。
答案 0 :(得分:6)
它不仅没有任何问题,而且它实际上是一种很好的做法:只暴露严格必要的东西。这样,调用者不能依赖于该方法将返回List<T>
这一事实,因此如果由于某种原因您需要更改实现以返回其他内容,则不会违反合同。但是,如果调用代码(错误地)对方法实际返回的内容做出了假设,那么调用代码可能会中断。
答案 1 :(得分:3)
返回IEnumerable<T>
类型的原因是调用者无法修改列表(不将其强制转换回列表)。如果您注意到所有(大多数?)扩展方法采用IEnumerable<T>
参数,那么您就知道扩展方法不会修改您的列表。
其次,List<T>
继承自IEnumerable<T>
。
修改强>
正如Thomas在评论中解释的那样,IEnumerable<T>
可以被强制转换为List<T>
并由调用者修改。如果您的主要目标是将其设为只读,则可以将列表作为myVar.AsReadOnly()
返回。但是类型是ReadOnlyCollection<T>
。
答案 2 :(得分:2)
它没有任何问题。
实际上返回具体类是满足“返回接口”要求的唯一方法。
如果您让特定类的知识潜入调用代码(List<T> r = (List<T>)MyMethod("ff")
),则可能存在缺陷。但是,如果你将结果视为界面(如你所愿),那就没关系。
答案 3 :(得分:1)
我认为这不是最佳的,因为它允许调用者强制转换为List<T>
,这依赖于实现细节。我会添加某种掩码,例如Select(x=>x)
。
动态类型的调用方可能甚至没有注意到您将列表转换为IEnumerable<T>
。对他而言,这只是List<T>
。
将内部永久List<T>
作为IEnumerable<T>
返回将是非常错误的,因为它允许调用者改变您的类的内部状态。但是,由于您在每次调用时返回List<T>
的新实例,而在其他任何地方都没有使用,所以此参数不适用于您的示例。