像这样的问题的答案:List<T> 或 IList<T> 总是认为返回接口比返回集合的具体实现更好。但我对此认为有些困惑。实例化接口是不可能的,因此如果你的方法返回一个接口,它实际上仍然返回一个特定的实现。我通过编写两个小方法进行了一些实验:
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>
的方法在我尝试向其中添加内容时会产生运行时错误。因此,那些不知道我的方法内部情况但必须向其中添加值的人被迫首先将我的IList
复制到List
中,以便能够在不冒错误风险的情况下添加值。当然,他们可以进行类型检查,看看他们是否正在处理List
或Array
,但如果他们不这样做,并且他们想要向集合中添加项目,则即使它已经是List
,他们也别无选择,只能将IList
复制到List
中。数组永远不应该公开为IList
吗?另一个我关心的问题基于链接问题的接受答案(强调是我的):
如果您通过库公开类供他人使用,通常应该通过接口而不是具体实现来公开它。这样做有助于在以后决定更改类的实现以使用不同的具体类时。在这种情况下,您的库的用户不需要更新其代码,因为接口没有更改。
如果只在内部使用,则可能无关紧要,使用List可能没问题。
想象一下,有人真的使用了从我的ExposeListIlist()
方法中获得的IList<T>
来添加/删除值。一切正常。但是现在,就像答案建议的那样,因为返回接口更加灵活,我返回一个数组而不是List(对我来说没有问题!),然后他们就会有一个惊喜...
简而言之:
1)公开接口会导致不必要的强制转换吗?这不重要吗?
2)有时,如果库的用户不使用强制转换,则当您更改方法时,他们的代码可能会出错,即使该方法仍然完全正常。
我可能过于深思熟虑了,但我不理解返回接口优于返回实现的共识。
IEnumerable<T>
可以获得编译时的安全性,同时仍然可以使用所有LINQ扩展方法,这些方法通常会尝试通过将其转换为特定类型(例如像ICollection<T>
这样的类型)来优化性能,以使用Count
属性而不是枚举它。 - Tim SchmelterIList<T>
。如果要公开返回它的方法,返回一个真正实现该接口的类型。 - CodeCasterIEnumerable<T>
。这样返回IList<T>
或List<T>
就可以了。 - Tim Schmelter