我正在编写一个库,并试图确定用于方法参数的最佳类型。我还试图确定在挑剔和获取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的解决方案,因为它支持最多的输入,我应该使用那个解决方案吗?
答案 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)
IEnumerable
是一个安全的选择。在很多情况下,除了列表以外的其他任何集合(例如IList
或LinkedList
之外,用户将没有Queue
对象,尤其是使用Linq中的对象时,尤其如此。
例如,如果他们使用someList.Select((x) => new OtherThing(x, "test"))
,使用Where
进行过滤等,那么它们将以IEnumerable
结尾。 System.Linq
中还提供了一种方便的myEnumerable.ToList()
,这是他们必须进行的一次额外转换,并且会对性能产生一定的影响,可能比您希望避免的转换更糟糕。
当然,有时出于性能原因,最好使用其他类型,尤其是在处理大量小值(例如byte[]
)或简化实现(例如,随机访问或修改数据。
您可能需要自己权衡取舍,尽管您可能会从该语言的标准类和其他流行的库中获得启发。对于公共库,在考虑二进制兼容性时也必须非常小心,例如,如果返回IEnumerable
,则可以将实现更改为使用其他实际类型,如果返回List
甚至是IList
,那么您在技术上可能会受到更多限制,而又不会破坏兼容性。