我有以下方法:
public List<Vehicle> Vehicles
{
get { return _vehicles; }
}
哪个会返回数据。如果我做以下事情;
public List<Vehicle> Vehicles
{
get { return _vehicles.OrderBy(v => v.Year).ToList(); }
}
变空了。如果我在此方法myList = vehicleList.Vehicles.OrderBy(x => x.Year)
之外调用orderby,则列表将包含所有需要的数据。
我很困惑为什么。
答案 0 :(得分:4)
在第一种情况下,您将返回对列表的引用,而不是列表的副本。如果稍后修改了内部列表,那么外部列表将能够观察到这些更改(因为它毕竟是相同的列表)。
当您从列表外部使用LINQ的OrderBy
方法时,它将推迟执行。直到你实际迭代该序列的结果它才会进入并查看列表;在哪一点上很可能已经改变了。
当您在属性获取器中使用ToList
时,您正在获取列表的副本,而不仅仅是将引用复制到它,因此它基本上是该时刻的快照。当你获得属性时,列表显然是空的,但当你迭代它时,它显然不是。
如果两者都具有延迟执行的能力,并且始终根据调用者未手动应用的排序访问此属性中的项目,那么您可以使用以下内容:
public IEnumerable<Vehicle> Vehicles
{
get { return _vehicles.OrderBy(v => v.Year); }
}
也就是说,如果在访问时总是对集合进行排序是很重要的,那么将项目简单地存储在已排序的庄园中可能是优选的,因此访问这些项目是便宜的。请考虑使用类似SortedSet
而非List
的内容。
答案 1 :(得分:2)
我认为你错过了一个事实,ToList()
创建了新的List<T>
,而不是返回基础的。{/ p>
所以当你打电话时:
var list = vehicleList.Vehicles;
list.Add(new Vehicle());
list.Add(new Vehicle());
Console.WriteLine(vehicleList.Vehicles.Count);
它将为您的第一个2
属性声明打印Vehicles
,为第二个属性声明打印0
。
这是因为您的第二个属性声明是将项目添加到刚使用List
调用创建的ToList()
,而不是_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>
而不是每次触发属性获取器时排序的标准List
。