列表在排序时变为空
本文关键字:排序 列表 | 更新日期: 2023-09-27 18:30:38
>我有以下方法:
public List<Vehicle> Vehicles
{
get { return _vehicles; }
}
这将返回数据。如果我执行以下操作;
public List<Vehicle> Vehicles
{
get { return _vehicles.OrderBy(v => v.Year).ToList(); }
}
它变得空。如果我在此方法之外调用 orderby myList = vehicleList.Vehicles.OrderBy(x => x.Year)
则列表将包含所有需要的数据。
我很困惑为什么。
在第一种情况下,您返回的是对该列表的引用,而不是列表的副本。 如果内部列表在以后修改,那么外部列表将能够观察到这些更改(因为它毕竟是同一个列表)。
当您从列表外部使用 LINQ 的 OrderBy
方法时,它将延迟执行。 直到您实际迭代该序列的结果,它才会查看列表;在这一点上很可能已经改变了。
当您在属性获取器中使用ToList
时,您正在获取列表的副本,而不仅仅是复制对它的引用,因此它基本上是该时刻的快照。 在你得到属性的时候,列表[显然]是空的,但是当你迭代它时,它[显然]不是。
如果两者都具有延迟执行的能力很重要,并且此属性中的项始终基于调用方未手动应用的排序进行访问,则可以改用如下所示的内容:
public IEnumerable<Vehicle> Vehicles
{
get { return _vehicles.OrderBy(v => v.Year); }
}
也就是说,如果在访问时始终对收藏进行排序很重要,那么最好只是将物品存储在已分类的庄园中,这样访问这些物品的成本就越便宜。 考虑改用类似SortedSet
的东西而不是List
。
我认为你错过了一个事实,即ToList()
创建新的List<T>
而不是返回底层。
因此,当您致电:
var list = vehicleList.Vehicles;
list.Add(new Vehicle());
list.Add(new Vehicle());
Console.WriteLine(vehicleList.Vehicles.Count);
它将打印您的第一个Vehicles
财产声明的2
,并为第二个0
。
这是因为使用第二个属性声明时,您将项添加到刚刚使用ToList()
调用创建的List
,而不是从支持字段添加到该_vehicles
。
要使其正常工作,请尝试以下操作:
public List<Vehicle> Vehicles
{
get { return (_vehicles = _vehicles.OrderBy(v => v.Year).ToList()); }
}
或者使用List<T>.Sort
方法而不是OrderBy
LINQ 扩展方法:
public List<Vehicle> Vehicles
{
get
{
_vehicles.Sort((v1, v2) => v1.Year.CompareTo(v2.Year));
return _vehicles;
}
}
但要明确一点:你应该高度考虑,拥有这种财产的整体想法是错误的。您需要始终对数据进行排序吗?使用正确的数据结构,例如SortedList<int, Vehicle>
,而不是每次触发属性 getter 时排序的标准List
。