如何在IList或IEnumerable之间选择方法参数类型

时间:2019-04-10 23:43:19

标签: c# parameters

我正在编写一个库,并试图确定用于方法参数的最佳类型。我还试图确定在挑剔和获取write方法定义之间的界限。

这是一些代码

public void MethodTakesIList(IList<MyClass> myClassInstances) {
  List<List<byte>> byteLists = GetByteLists(myClassInstances.Count);
  for (int i = 0; i < myClassInstances.Count; i++) {
    ProcessBytesAndMyClassInstance(byteLists[i], myClassInstances[i]);
  }
} 

public void MethodTakesIEnumerable(IEnumerable<MyClass> myClassInstances) {
  List<List<byte>> byteLists = GetByteLists(myClassInstances.Count());
  int i = 0;
  foreach(MyClass instance in myClassInstances) {
    ProcessBytesAndMyClassInstance(byteLists[i], instance);
    i++;
  }
}

this文章中指出,“我应该始终使用仅为您真正使用的方法提供合同的类型”。采用IEnumerable的方法仍定义循环中使用的索引。由于此索引将指向有效的条目如果myClassInstances是一个列表,这是否意味着我应该只使用接受IList的方法?我现在可以使用IList的索引器。还是因为存在一种接受IEnumerable的解决方案,因为它支持最多的输入,我应该使用那个解决方案吗?

2 个答案:

答案 0 :(得分:1)

如果我是您,我将从Microsoft如何实现LINQ中获得启发。许多可能从使用集合类型中受益的运算符仍然将IEnumerable<TSource>作为源数据,但是他们只是尝试将其强制转换为ICollection<TSource>以直接访问索引和其他属性。 / p>

以{对此稍有修改的)Count为例,

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    ICollection<TSource> collection = source as ICollection<TSource>;
    if (collection != null)
    {
        return collection.Count;
    }
    ICollection collection2 = source as ICollection;
    if (collection2 != null)
    {
        return collection2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num = checked(num + 1);
        }
        return num;
    }
}

如果输入类型可转换为集合,则Count运算符只返回计数;否则,将遍历列表。

这样一来,您就可以充分利用这两种类型。

答案 1 :(得分:0)

如果您不确定人们将如何使用API​​,通常

IEnumerable是一个安全的选择。在很多情况下,除了列表以外的其他任何集合(例如IListLinkedList之外,用户将没有Queue对象,尤其是使用Linq中的对象时,尤其如此。

例如,如果他们使用someList.Select((x) => new OtherThing(x, "test")),使用Where进行过滤等,那么它们将以IEnumerable结尾。 System.Linq中还提供了一种方便的myEnumerable.ToList(),这是他们必须进行的一次额外转换,并且会对性能产生一定的影响,可能比您希望避免的转换更糟糕。

当然,有时出于性能原因,最好使用其他类型,尤其是在处理大量小值(例如byte[])或简化实现(例如,随机访问或修改数据。

您可能需要自己权衡取舍,尽管您可能会从该语言的标准类和其他流行的库中获得启发。对于公共库,在考虑二进制兼容性时也必须非常小心,例如,如果返回IEnumerable,则可以将实现更改为使用其他实际类型,如果返回List甚至是IList,那么您在技术上可能会受到更多限制,而又不会破坏兼容性。