Answers:
我遵循两个规则:
因此,在编写要使用集合的函数或方法时,请不要将其写入列表,而要写入IList <T>,ICollection <T>或IEnumerable <T>。即使System.Object也可以是T,所以通用接口即使对于异构列表也仍然可以使用。如果您决定在以后使用堆栈或其他数据结构,这样做将为您省去麻烦。如果在函数中需要做的只是遍历它,那么IEnumerable <T>实际上就是您所需要的。
另一方面,当从函数中返回对象时,您希望为用户提供尽可能丰富的操作集,而不必进行操作。因此,在这种情况下,如果内部是List <T>,则将副本作为List <T>返回。
if...else
带有is
关键字的链来进行计算。为其提供更丰富的类型,并最终强制转换为它并使用它。因此,不一定要通过使用基本界面来隐藏任何东西,而不仅仅是掩盖它。但是,使其变得更困难也可能使使用代码的作者对他们的使用方式进行三思。
Add()
并且Remove()
可能会产生超出该集合的影响。返回只读接口,例如,IEnumerable
通常是数据检索方法的方法。您的消费者可以根据需要将其投影到更丰富的类型中。
FxCop检查的Microsoft准则不建议在公共API中使用List <T>-最好使用IList <T>。
顺便说一句,我现在几乎总是将一维数组声明为IList <T>,这意味着我可以一致地使用IList <T> .Count属性而不是Array.Length。例如:
public interface IMyApi
{
IList<int> GetReadOnlyValues();
}
public class MyApiImplementation : IMyApi
{
public IList<int> GetReadOnlyValues()
{
List<int> myList = new List<int>();
... populate list
return myList.AsReadOnly();
}
}
public class MyMockApiImplementationForUnitTests : IMyApi
{
public IList<int> GetReadOnlyValues()
{
IList<int> testValues = new int[] { 1, 2, 3 };
return testValues;
}
}
人们似乎总是忽略一个重要的事情:
您可以将纯数组传递给接受IList<T>
参数的对象,然后可以调用IList.Add()
并收到运行时异常:
Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.
例如,考虑以下代码:
private void test(IList<int> list)
{
list.Add(1);
}
如果按如下所示进行调用,则将获得运行时异常:
int[] array = new int[0];
test(array);
发生这种情况是因为将纯数组与 IList<T>
违反了Liskov替换原理。
因此,如果您要致电,则IList<T>.Add()
可能需要考虑使用List<T>
而不是IList<T>
。
List<T>
过IList<T>
,你也应该知道为什么原因,IList<T>
值得推荐。(例如,blogs.msdn.microsoft.com / kcwalina / 2005/09/26 /…)
IList<T>.Add()
。我并不是说您不应该使用IList<T>
-我只是指出可能的陷阱。(如果可以的话,我倾向于使用IEnumerable<T>
或IReadOnlyList<T>
或IReadOnlyCollection<T>
优先选择IList<T>
。)
IEnumerable
您应尝试使用适合您目的的最不特定的类型。
IEnumerable
没有比的具体IList
。
你用IEnumerable
,当你通过集合中的项目要循环。
IList
IList
工具IEnumerable
。
你应该用IList
当您需要按索引访问集合,添加和删除元素等时, ...
列出
List
工具IList
。
我认为这类事情没有严格的规定,但我通常会遵循使用最轻巧的方法的指导原则,直到绝对必要为止。
例如,假设您有一个Person
班级和一个Group
班级。一个Group
实例有很多人,因此这里的List才有意义。当我在其中声明列表对象时,Group
我将使用IList<Person>
并将其实例化为List
。
public class Group {
private IList<Person> people;
public Group() {
this.people = new List<Person>();
}
}
而且,即使您甚至不需要任何东西,IList
也可以随时使用IEnumerable
。对于现代的编译器和处理器,我认为速度之间并没有真正的区别,所以这更多地是样式问题。
在通常遇到的情况下,我很少直接使用IList。
通常我只是将其用作方法的参数
void ProcessArrayData(IList almostAnyTypeOfArray)
{
// Do some stuff with the IList array
}
这将使我可以对.NET框架中的几乎所有数组进行通用处理,除非它使用IEnumerable而不是IList,但有时会发生这种情况。
实际上,这取决于您需要的功能。我建议在大多数情况下使用List类。IList最适合需要创建自定义数组的情况,该数组可能具有一些非常具体的规则,希望将这些规则封装在集合中,这样您就不必重复自己了,但仍然希望.NET将其识别为列表。
AList对象使您可以创建列表,对其进行添加,删除,更新,对其进行索引等。只要您需要通用列表(在其中指定对象类型)就可以使用List。
另一方面,IList是一个接口。基本上,如果要创建自己的List类型,请说一个名为BookList的列表类,然后可以使用Interface为新类提供基本的方法和结构。IList适用于想要创建自己的实现List的特殊子类的情况。
另一个区别是:IList是一个接口,无法实例化。List是一个类,可以实例化。它的意思是:
IList<string> MyList = new IList<string>();
List<string> MyList = new List<string>