什么是API中返回的最佳集合类型

leo*_*ora 10 c# collections

我一直认为在使用公共API时,返回的数组比列表更好,但现在似乎在列表上有所有这些函数都可以通过LINQ等获得.

这里是否已更改了返回基元或对象集合的最佳实践?

例如:

Order[] GetOrders();
List<Order> GetOrders();
IEnumerable<Order> GetOrders();
IQueryable<Order> Get Orders();
Run Code Online (Sandbox Code Playgroud)

Jay*_*Jay 6

你想要这个集合是不可变的吗?IEnumerable<T> 可变的?IList<T>

你需要索引吗? IList<T>

使用列表或数组,API使用者具有添加,删除,删除,清除等功能.

使用a IEnumerable<T>,API使用者获得一个"包"项,没有特定的顺序,没有索引,也没有方法来修改集合.

在某些有限的情况下,您可能希望返回一个IQueryable<T>,但它们通常特定于逐个构建查询.

一般来说,我默认为IEnumerable<T>.我可能会使用a List<T>作为支持字段,但只想让用户Add(),例如 - 不要删除,清除或其他任何东西,所以我声明一个public void Add<T>(T item)只是将项目添加到支持字段列表.


Dre*_*kes 6

因为我通常只从属性/方法返回不可变(不可修改)的对象,所以这个答案假定你想要做同样的事情.

不要忘记ReadOnlyCollection<T>哪些返回仍然可以通过索引访问的不可变集合.

如果你正在使用IEnumerable<T>并将你的类型释放到无法控制的荒野中,请注意以下事项:

class MyClass {
    private List<int> _list;
    public IEnumerable<int> Numbers {
        get { return _list; }
    }
}
Run Code Online (Sandbox Code Playgroud)

因为用户可以这样做并弄乱你班级的内部状态:

var list = (List<int>)myClass.Numbers;
list.Add(123);
Run Code Online (Sandbox Code Playgroud)

这将违反财产的只读意图.在这种情况下,你的getter应该是这样的:

    public IEnumerable<int> Numbers {
        get { return new ReadOnlyCollection<int>(_list); }
    }
Run Code Online (Sandbox Code Playgroud)

或者你可以打电话_list.ToReadOnly().我完整地写出来以显示类型.

这将阻止任何人修改你的状态(除非他们使用反射,但除非你构建像许多函数式编程语言中使用的那些不可变集合,否则这很难停止,这是另一个故事).

如果您正在返回只读集合,那么最好将成员声明ReadOnlyCollection<T>为然后某些操作执行得更快(获取计数,按索引访问项目,复制到另一个集合).

就个人而言,我希望看到框架包含并使用如下界面:

public interface IReadOnlyCollection<T> : IEnumerable<T>
{
    T this[int index] { get; }
    int Count { get; }
    bool Contains(T item);
    void CopyTo(T[] array, int arrayIndex);
    int IndexOf(T item);
}
Run Code Online (Sandbox Code Playgroud)

你可以使用扩展方法获得所有这些功能,IEnumerable<T>但它们并不是那么高效.


Pat*_*lug 5

我认为最常用的类型是 IEnumerable<T>

  • 使用IEnumerable<T>返回类型,您可以使用yield关键字,这将启用延迟枚举和方法的执行.(例如,一个常见的抱怨是System.IO.Path.GetFiles()不返回一个IEnumerable<T>但返回一个数组,这意味着当你调用该方法时,无论你是否需要它们,都需要枚举所有项目. - 你有相同的缺点List<T>)
  • 大多数LINQ扩展方法都适用于 IEnumerable<T>
  • IEnumerable<T>返回类型不承担具体的有关呼叫者的东西.如果调用者需要列表或数组,他们总是可以创建一个.
  • IEnumerable<T>List<T>和实现,Array因此很容易更改方法的实现,仍然支持以前的返回类型.