我知道IList是接口,List是具体类型,但我仍然不知道何时使用每一个。我现在做的是,如果我不需要Sort或FindAll方法,我使用接口。我说的对吗?是否有更好的方法来决定何时使用接口或具体类型?


当前回答

我有两条原则:

接受最基本的工作类型 返回用户需要的最丰富的类型

因此,当编写一个接受集合的函数或方法时,不要让它接受List,而是让它接受IList<T>、ICollection<T>或IEnumerable<T>。泛型接口即使对于异构列表也仍然有效,因为System。Object也可以是T。如果您决定在以后使用Stack或其他数据结构,这样做将为您省去麻烦。如果在函数中所需要做的只是逐个遍历它,那么IEnumerable<T>才是真正需要的。

另一方面,当从函数返回一个对象时,您希望为用户提供尽可能丰富的操作集,而不需要他们进行强制转换。在这种情况下,如果内部是List<T>,返回一个List<T>的副本。

其他回答

有一件重要的事情,人们似乎总是忽视:

你可以将一个普通数组传递给接受IList<T>参数的对象,然后你可以调用IList. add(),并将收到一个运行时异常:

未处理异常:系统。NotSupportedException:集合大小固定。

例如,考虑以下代码:

private void test(IList<int> list)
{
    list.Add(1);
}

如果你像下面这样调用它,你会得到一个运行时异常:

int[] array = new int[0];
test(array);

这是因为使用带有IList<T>的普通数组违反了利斯科夫替换原则。

因此,如果你调用IList<T>. add(),你可能需要考虑使用List<T>而不是IList<T>。

IEnumerable 您应该尝试使用最不特定的类型来满足您的目的。 IEnumerable没有IList那么具体。 当您希望循环遍历集合中的项时,可以使用IEnumerable。

IList IList实现了IEnumerable。 当你需要通过索引访问你的集合,添加和删除元素等时,你应该使用IList。

列表 List实现了IList。

在我通常遇到的情况下,我很少直接使用IList。

通常我只是把它用作方法的参数

void ProcessArrayData(IList almostAnyTypeOfArray)
{
    // Do some stuff with the IList array
}

这将允许我对. net框架中的几乎任何数组进行泛型处理,除非它使用IEnumerable而不是IList,这种情况有时会发生。

这实际上取决于你需要什么样的功能。我建议在大多数情况下使用List类。当你需要创建一个自定义数组,其中可能包含一些非常特定的规则,你希望将这些规则封装在一个集合中,这样你就不会重复自己的操作,但仍然希望. net将其识别为一个列表时,IList是最好的选择。

由FxCop检查的微软指南不鼓励在公共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实现而不是list。这是真的,例如,当你使用NHibernate,它在检索数据时将列表转换为NHibernate包对象。

如果List是您将用于某个集合的唯一实现,则可以将其声明为具体的List实现。