我找到了.ToList()
的更多代码,其中需要对IList<t>
方法调用结果进行列表操作。
因此,当返回IList<t>
的方法在内部使用List作为实例时,在使用ToList()
之前进行某种形式的检查似乎是合适的。
ToList
扩展程序似乎无法检查源是否已经是List。
请参阅下面的反编译源。
是一个自定义扩展,以避免看起来像列表重复一个好主意? 例如
public static List<T> ToListWCheck<T>(this IEnumerable<T> source) {
if (source == null){ return null;}
var isListAlready = source as List<T>;
return isListAlready ?? source.ToList();
}
有没有更好的方法来处理IList&lt;&gt;列出&lt;&gt;有效;吗
// Extract from System.Linq.Enumerable
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull("source");
else
return new List<TSource>(source);
}
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Collections.Generic.List`1"/> class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new list.</param><exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is null.</exception>
[__DynamicallyInvokable]
public List(IEnumerable<T> collection)
{
if (collection == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
ICollection<T> collection1 = collection as ICollection<T>;
if (collection1 != null)
{
int count = collection1.Count;
if (count == 0)
{
this._items = List<T>._emptyArray;
}
else
{
this._items = new T[count];
collection1.CopyTo(this._items, 0);
this._size = count;
}
}
else
{
this._size = 0;
this._items = List<T>._emptyArray;
foreach (T obj in collection)
this.Add(obj);
}
}
答案 0 :(得分:2)
对于那些可能不知道的人,从.NET 4.5开始添加了IReadOnlyList<T>
。当我知道我创建列表一次并且不打算再次更改它时,我已经开始使用此代替IEnumerable<T>
作为返回值。如果沿着调用链一致地使用它,则可以避免在整个地方创建多个列表副本。实际上,我的一个应用程序在列表上执行了大量操作,从而显着提高了性能。
对于更强大的保证,新的Immutable Collections包中有ImmutableList<T>
,它不是框架的严格组成部分,但是作为Microsoft的官方扩展版本发布。在这个和上面之间,我认为我们会看到在任何地方使用IEnumerable的速度都很慢。我认为这是一件好事,因为以前很难判断一个方法是否使用了延迟执行,这意味着你经常会立即调用ToList()或ToArray(),在函数创建时创建不必要的副本,在内部返回一个集合。
答案 1 :(得分:1)
将一些评论(我和其他人)转变为可行的答案......
如果有诱惑要覆盖.ToList()
本身,绝对不要这样做。 .ToList()
的功能是枚举枚举并创建它的内存列表。如果该枚举已经一个列表,则无关紧要。使它重要将打破可枚举的抽象。更不用说创建一个{em>有时返回新列表的.ToList()
方法,有时返回对原始源的引用肯定引入副作用。微妙,难以调试的副作用。
在创建一个单独的方法方面,它肯定是可行的,但我会谨慎行事。我同意@bas发布的评论,它更多的是代码味道而不是其他任何东西。如果您在IList<T>
上创建这样的方法,那么它就是多余的。如果你在IEnumerable<T>
上创建它,那么你又会创建一些有时做一件事而有时做另一件事的事情,这巧妙地打破了抽象。
您可以创建此方法,但我会非常小心该方法的名称和intellisense文档。清楚地宣传非常它的作用。方法名称绝不应该是错误信息。但也要问问自己,潜在的性能增益是否超过抽象的微妙损失和实现的微妙耦合。我怀疑它没有。并且您不希望发现自己处于这样一种位置:在整个代码库中只使用然后来发现它的效果并不像希望的那样好,因为还原所有这些用途反过来也会产生副作用和错误。
你能做到吗?是。你应该?这可能没有必要。