何时使用IList和何时使用List

时间:2020-03-05 18:40:56  来源:igfitidea点击:

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

解决方案

回答

我认为这类事情没有严格的规定,但我通常会遵循使用最轻巧的方法的指导原则,直到绝对必要为止。

例如,假设我们有一个" 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将其识别为列表。

回答

如果我们使用的是单个方法(有时甚至是单个类或者程序集),并且外面没有人看我们在做什么,请使用List的完整性。但是,如果要与外部代码进行交互(例如,从方法中返回列表),则只想声明该接口,而不必将自己绑定到特定的实现,尤其是如果我们无法控制谁针对编译进行控制时之后的代码。如果我们从一个具体的类型开始,并且决定更改为另一个,即使它使用相同的接口,除非我们从一个接口或者抽象基类型开始,否则我们将破坏其他人的代码。

回答

仅在需要时才应使用该接口,例如,将列表强制转换为List以外的IList实现。例如,当我们使用NHibernate时,这是正确的,它在检索数据时将ILists强制转换为NHibernate bag对象。

如果List是我们将用于特定集合的唯一实现,请随时将其声明为具体的List实现。

回答

始终最好使用最低的基本类型。这使界面的实现者或者方法的使用者有机会在幕后使用他们喜欢的任何东西。

对于集合,我们应该尽可能使用IEnumerable。这提供了最大的灵活性,但并不总是适用。

回答

我遵循两个规则:

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

因此,在编写要使用集合的函数或者方法时,请不要将其写入列表,而要写入IList <T>,ICollection <T>或者IEnumerable <T>。即使System.Object也可以是T,所以通用接口即使对于异构列表也仍然可以使用。如果我们决定在以后使用堆栈或者其他一些数据结构,这样做将使我们免于头痛。如果在函数中需要做的只是遍历整个函数,则IEnumerable <T>确实是我们所需要的。

另一方面,当从函数中返回对象时,我们希望为用户提供尽可能丰富的操作集,而不必进行操作。因此,在这种情况下,如果内部是List <T>,则将副本作为List <T>返回。

回答

我会同意Lee的建议,但不要返回。

如果指定方法以返回接口,则意味着以后可以随意更改确切的实现,而无需使用任何消耗方法。我以为我永远都不需要从List <T>进行更改,而是不得不稍后进行更改以使用自定义列表库来提供它提供的额外功能。因为我只返回了IList <T>,所以使用该库的所有人员都无需更改其代码。

当然,这仅适用于外部可见的方法(即公共方法)。我甚至在内部代码中都亲自使用接口,但是由于我们可以自行更改所有代码(如果我们进行重大更改),因此这并不是绝对必要的。

回答

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甚至更好的IEnumerable接口,以便以后可以方便地切换实现。

但是,在.NET 2.0中,令人烦恼的是IList没有Sort()方法。我们可以改用提供的适配器:

ArrayList.Adapter(list).Sort()