我试图在foreach循环中使用OrderBy
对一些列表进行排序,但是不知何故,它们在循环外部无法保持排序顺序。下面是一些简化的代码和注释,以突显问题:
public class Parent
{
// Other properties...
public IList<Child> Children { get; set; }
}
public IEnumerable<Parent> DoStuff()
{
var result = DoOtherStuff() // Returns IEnumerable<Parent>
.OrderByDescending(SomePredicate)
.ThenBy(AnotherPredicate); // This sorting works as expected in the return value.
foreach (Parent parent in result)
{
parent.Children = parent.Children.OrderBy(YetAnotherPredicate).ToList();
// When I look at parent.Children here in the debugger, it's sorted properly.
}
return result;
// When I look at the return value, the Children are not sorted.
}
然而,当我这样赋值result
时:
var result = DoOtherStuff()
.OrderByDescending(SomePredicate)
.ThenBy(AnotherPredicate)
.ToList(); // <-- Added ToList here
如果返回值在每个父级中都按照子级正确排序,则具有正确排序的Children。
List<T>
与IEnumerable<T>
在foreach循环中的行为有何不同?
由于将result转换为List可以解决foreach循环中排序问题,因此似乎存在某种差异。在使用foreach进行迭代时,第一个代码片段创建了一个复制每个元素的迭代器(因此我的更改应用于副本而不是result
中的原始对象),而使用ToList()
则使枚举器给出指针。发生了什么?
DoOtherStuff
方法实际上不会再次被调用,但是方法内的代码可能会再次执行。该方法返回一个枚举器,当它被重新创建时,创建它的代码将再次运行。 - GuffaIEnumerable<T>
和System.Linq
的工作原理,这个答案非常准确。 - wlyles