Linq OrderBy不对List<;T>;.如何对列表进行排序
本文关键字:排序 列表 不对 OrderBy List lt Linq gt | 更新日期: 2023-09-27 17:54:45
OrderBy子句出现问题,对排序没有任何影响。我在调试器中仔细检查了这一点,并确保这是一种代码的排序行被击中的情况,并在它之后查看结果,没有应用OrderBy。
public static IEnumerable<DDLOptions<TValueType>> GetDDLOptionsViewModel<TClass, TValueType>(
IEnumerable<TClass> list,
Func<TClass, TValueType> value,
Func<TClass, string> displayText,
bool sort = true
)
{
List<DDLOptions<TValueType>> ddlOptions;
ddlOptions = list.Select(
l => new DDLOptions<TValueType>
{
Value = value(l),
DisplayText = displayText(l)
}
).ToList(); <========== Works if I put the Order By here.
if (sort)
{
ddlOptions.OrderBy(l => l.DisplayText); <===== Does NOT work here.
}
return ddlOptions;
}
OrderBy
返回一个执行排序的查询:它不会修改原始列表(而类似List<T>.Sort
的东西会修改原始列表(
相反,可以尝试以下方法:
ddlOptions = ddlOptions.OrderBy(l => l.DisplayText).ToList();
您可能想考虑ddlOptions
的类型,或者在我们进行额外的ToList
时在哪里/如何返回数据,但无论如何,这可能是本例的一个小问题。
请注意,这同样适用于其他LINQ函数,如GroupBy、Distinct、Concat-所有函数都返回结果,而不是修改源集合。
尝试:
if (sort)
{
ddlOptions = ddlOptions.OrderBy(l => l.DisplayText); <===== Should work now.
}
正如其他人所说,你需要将OrderBy
的结果分配给某个东西,因为它不会改变它所作用的序列。最简单的方法是将ddlOptions
设置为IEnumerable
而不是List
,这样你就可以将结果分配给它。选择上的ToList
调用也不需要:
public static IEnumerable<DDLOptions<TValueType>> GetDDLOptionsViewModel<TClass, TValueType>(
IEnumerable<TClass> list,
Func<TClass, TValueType> value,
Func<TClass, string> displayText,
bool sort = true
)
{
IEnumerable<DDLOptions<TValueType>> ddlOptions;
ddlOptions = list.Select(
l => new DDLOptions<TValueType>
{
Value = value(l),
DisplayText = displayText(l)
}
);
if (sort)
{
ddlOptions = ddlOptions.OrderBy(l => l.DisplayText);
}
return ddlOptions;
}
请注意,此版本的方法将使用延迟执行,因此在迭代序列之前不会实际执行Select/OrderBy。如果您不想这样做,可以在return
行中添加ToList
。
您需要键入:
ddlOptions = ddlOptions.OrderBy(l => l.DisplayText);
OrderBy
不对List<T>
或任何其他IEnumerable<T>
进行排序。它生成一个新的、排序的IEnumerable<T>
。因此调用ddlOptions.OrderBy(...)
不会修改ddlOptions
。
如果您有一个List<T>
并希望对其进行排序,则可以使用Sort
方法,特别是将Comparison<T>
作为参数的重载。这实际上是对列表进行排序,而不是返回一个新的IEnumerable
。
Comparison<T>
是代表一个函数的委托,该函数取T
中的两个,如果第一个"小于"第二个,则返回负数;如果第一个比第二个"大",则返回正数;如果一个没有在另一个之前或之后排序,则返回零。
在这种情况下,你不必记住这一点。相反,你可以这样做:
ddlOptions.Sort((x, y) => string.CompareOrdinal(x.DisplayText, y.DisplayText));
您正在传递一个函数,该函数接受列表中的两个项,并返回它们的DisplayText
属性的比较结果,这些属性将是负数、0或正数。
有时我们使用OrderBy
,因为不会修改原始列表。但是,如果修改列表是我们想要的,那么我们可以使用Sort
。