这样的问题的答案:List <T>或IList <T>似乎总是同意,返回接口比返回集合的具体实现更好。但是我为此感到挣扎。实例化接口是不可能的,因此,如果您的方法正在返回接口,则实际上它仍在返回特定的实现。我通过编写2个小方法对此进行了一些试验:
public static IList<int> ExposeArrayIList()
{
return new[] { 1, 2, 3 };
}
public static IList<int> ExposeListIList()
{
return new List<int> { 1, 2, 3 };
}
并在我的测试程序中使用它们:
static void Main(string[] args)
{
IList<int> arrayIList = ExposeArrayIList();
IList<int> listIList = ExposeListIList();
//Will give a runtime error
arrayIList.Add(10);
//Runs perfectly
listIList.Add(10);
}
在两种情况下,当我尝试添加新值时,编译器都不会给我任何错误,但是很显然,IList<T>
当我尝试向其中添加某些内容时,将数组公开为的方法会导致运行时错误。因此,不知道我的方法正在发生什么而必须为其添加值的人,被迫首先将my复制IList
到a List
,以便能够添加值而不会冒错误的风险。当然,他们可以进行类型检查以查看是否正在处理aList
或an Array
,但如果不这样做,并且他们想将项目添加到集合中,则别无选择将其复制IList
到a List
,即使它已经是一个List
。不应将数组公开为IList
吗?
我的另一个关注点是基于链接问题的接受答案(强调我的意思):
如果要通过供他人使用的库公开类,则通常希望通过接口而不是具体的实现公开它。如果您以后决定更改类的实现以使用其他具体类,则这将有所帮助。在这种情况下,库的用户无需更新其代码,因为界面不会更改。
如果您仅在内部使用它,则可能不太在意,并且可以使用List。
想象有人实际上使用了我IList<T>
从我的ExposeListIlist()
方法中获得的东西,就像添加/删除值一样。一切正常。但是现在就像答案所暗示的那样,因为返回接口更灵活,所以我返回一个数组而不是一个List(对我来说这没问题!),那么他们可以请客了……
TLDR:
1)暴露接口会导致不必要的强制转换?没关系吗?
2)有时,如果库的用户不使用强制转换,则即使您的方法仍然可以正常使用,当您更改方法时,他们的代码也会中断。
我可能对此过于考虑,但是我没有得到普遍的共识,即返回接口比返回实现更可取。
IEnumerable<T>
,您将具有编译时安全性。您仍然可以使用所有LINQ扩展方法,这些方法通常通过将其强制转换为特定类型来尝试优化性能(例如ICollection<T>
使用Count
属性而不是枚举属性)。