C# ToList()可以更改列表中项目的顺序吗?
当C# ToList()可以更改列表中项目的顺序吗?,c#,list,C#,List,当 list2=list1.ToList()和两者都属于List?类型,应该没有什么不同。检查源代码 public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { if (source == null) throw Error.ArgumentNull("source"); return new List<TSource>(source
list2=list1.ToList()
和两者都属于List
?类型,应该没有什么不同。检查源代码
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
公共静态列表列表(此IEnumerable源代码){
if(source==null)抛出错误.ArgumentNull(“source”);
返回新列表(源);
}
以及创建列表时的零件
// Constructs a List, copying the contents of the given collection. The
// size and capacity of the new list will both be equal to the size of the
// given collection.
//
public List(IEnumerable<T> collection) {
if (collection==null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
Contract.EndContractBlock();
ICollection<T> c = collection as ICollection<T>;
if( c != null) {
int count = c.Count;
if (count == 0)
{
_items = _emptyArray;
}
else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
}
else {
_size = 0;
_items = _emptyArray;
// This enumerable could be empty. Let Add allocate a new array, if needed.
// Note it will also go to _defaultCapacity first, not 1, then 2, etc.
using(IEnumerator<T> en = collection.GetEnumerator()) {
while(en.MoveNext()) {
Add(en.Current);
}
}
}
}
//构造一个列表,复制给定集合的内容。这个
//新列表的大小和容量都将等于
//给定集合。
//
公共列表(IEnumerable集合){
if(集合==null)
ThrowHelper.ThrowArgumentNullException(argument.collection除外);
Contract.EndContractBlock();
ICollection c=作为ICollection的集合;
如果(c!=null){
int计数=c计数;
如果(计数=0)
{
_项目=_emptyArray;
}
否则{
_项目=新的T[计数];
c、 复制到(_项,0);
_大小=计数;
}
}
否则{
_尺寸=0;
_项目=_emptyArray;
//此可枚举项可能为空。如果需要,让Add分配一个新数组。
//注意,它也将首先转到_defaultCapacity,而不是1,然后是2,以此类推。
使用(IEnumerator en=collection.GetEnumerator()){
while(en.MoveNext()){
添加(当前版本);
}
}
}
}
简单的答案是否定的,
ToList
只会在源枚举上循环,并保持相同的顺序<代码>列表保证了顺序,因此对其调用ToList
不会改变顺序
然而,更微妙的回答是,您可能不是从列表开始的,可能有一个更通用的IEnumerable
,它根本不能保证顺序。这意味着对source.ToList()
的多个调用可能会产生不同的输出
然而在实践中,几乎所有IEnumerable的实现都将保持秩序。首先:可以肯定地说,每个人都期望这样。但是为什么呢
根据文档,采用IEnumerable
的List
的构造函数保证了顺序的保留:
元素被复制到列表中的顺序与集合的枚举器读取的顺序相同
而.ToList()
的文档没有做出这样的承诺(不过也没有说任何相反的话)
在内部,一个使用另一个,因此您是安全的,但是如果.ToList()
的内部实现发生更改,则不能保证您是安全的。所以如果你想确定,你应该调用newlist(oldList)代码>直接
如果你对它吹毛求疵。。。我无法保证IEnumerable
接口也会按顺序返回列表中的元素。因此,从这两个方面来看,您都必须了解是什么,如果您需要依赖它,可以编写一些单元测试来断言此行为,以便在当前行为发生变化时立即得到通知。如果list1
的顺序一致,则list2
的顺序将相同
list1
可能是某种类型,它本身并不保证每次枚举时都具有相同的顺序,在这种情况下,两者当然可能有所不同,但造成这种情况的是list1
的枚举逻辑,而不是ToList()
。(列表1的名称表明它本身就是一个列表,在这种情况下,顺序肯定是相同的)
这里的一个答案已经包括ToList()
的一个实现的源代码。它不是唯一存在的ToList()
版本,corefx优化的情况比netfx多得多,但所有版本生成列表的顺序与源代码在枚举时提供列表的顺序相同
另一个答案是,文档中并没有保证这一点,只是描述了采用枚举的列表
构造函数的重载(顺便说一句,它不是所有情况下ToList()
的所有实现都使用的唯一构造函数)
但是,如果更改为ToList()
,但未承诺维持订单,则不会被接受
考虑someSource.OrderBy(x=>x.ID).ToList()的情况。在这种情况下(顺便说一句,这是corefx中优化的情况),如果ToList()
可以更改顺序,则显然会删除OrderBy()的点
好的,那么如果有人改变了ToList()
,而不是承诺维持秩序,而是将OrderBy()
视为特例,该怎么办?(毕竟,在一个版本中,出于性能原因,这已经是一个特例)。好的,这仍然会破坏saysomeSource.OrderBy(x=>x.ID).Where(x=>!x.Deleted).ToList()
。总之,如果我们有一个版本的ToList()
没有维护顺序,我们就能够提出某种linq查询,其中一个给定的顺序是由查询的另一部分承诺的,而ToList()
的这种实现破坏了整个查询的承诺
因此,除非使用特殊的大小写,否则一个明确不承诺维护顺序的源(ParallelEnumerable
不承诺,除非您使用AsOrdered()
,因为除非在并行处理中确实需要,否则不维护顺序有很多好处)我们无法对ToList()进行更改
无法维持秩序