列表在方法 C# 中不会更改
本文关键字:方法 列表 | 更新日期: 2023-09-27 18:29:45
我有一个类Items
,我尝试对项目列表进行排序:
private static void Sort(List<Items> items)
{
.
.
.
SortDesc(items);
}
private static void SortDesc(List<Items> items)
{
items = items.OrderByDescending(x => x.Neto).ToList();
}
当调试器在 SortDesc()
中时,列表中的项按Neto DESC
排序。当我继续并返回Sort()
时,列表回到我打电话之前的状态SortDesc()
。
默认情况下,List<T>
通过 ref 发送,那么为什么这不起作用呢?
谢谢!
您正在使用以下代码行更改items
指向的内存中的引用:
items = items.OrderByDescending(x => x.Neto).ToList();
调用 SortDesc
方法时,列表对象通过引用传递。然后你正在创建新列表。在此之后,您将它设置为items
参数。在此之后,items
指向新的引用,而不是以前的引用。但是,真正的items
仍然指向旧的。
因此,您必须返回新创建的列表:
private static List<Items> SortDesc(List<Items> items)
{
return items.OrderByDescending(x => x.Neto).ToList();
}
然后,只需在Sort
方法中设置它:
items = SortDesc(items);
PS:您也可以显式使用ref
关键字来获得所需的结果,但这实际上不是首选方式。(...void SortDesc(ref List<Items> items)
(。你可以从他对这个问题的回答中读到@JonSkeet答案 何时使用 ref 以及何时在 C# 中不需要:
有用的答案:你几乎不需要使用ref/out。它基本上是一个 获取另一个返回值的方式,通常应避免 正是因为这意味着该方法可能也在尝试这样做 多。
您需要退回订购的物品,
private static List<Items> SortFromTheHighPriceToLowPriceByNeto(List<Items> items)
{
items = items.OrderByDescending(x => x.Neto).ToList();
return items;
}
> 调用 SortDesc
时,会将对原始items
变量的引用的副本传递给方法。因此,在重新分配item
的方法中,您将新引用分配给原始引用的副本,而不是原始引用本身。原始引用保持不变。
为了更新原始引用,您需要通过引用传递items
。这样做:
private static void SortDesc(ref List<Items> items)
{
items = items.OrderByDescending(x => x.Neto).ToList();
}
如果您这样做,则呼叫将变为SortDesc(ref items)
。这将按预期工作。
默认情况下,
List<T>
通过 ref 发送,那么为什么这不起作用呢?
否,所有未特别标记的参数都是按值传递的(它适用于引用类型和值类型(。如果您将方法更改为ref
它将起作用:
private static void SortDesc(ref List<Items> items)
{
items = items.OrderByDescending(x => x.Neto).ToList();
}
正如法哈德的回答中所解释的那样,这里的要点是.ToList()
创造了一个新的List<Items>
实例。旧实例保持不变。上面items = ...
赋值会更改引用的值(从引用原始实例到引用新实例(,因此如果参数是按值计算的,它将不起作用。
由于您创建了一个新实例,因此最好直接返回它:
private static List<Items> SortDesc(List<Items> items)
{
return items.OrderByDescending(x => x.Neto).ToList();
}
但是,既然您void
方法,也许您想对同一列表进行排序而不是创建另一个列表?
在这种情况下,有一些可能性。一种是在List<>
上使用Sort
方法,像这样:
private static void SortDesc(List<Items> items)
{
items.Sort((x, y) => y.Neto.CompareTo(x.Neto)); // unstable
}
或:
private static void SortDesc(List<Items> items)
{
items.Sort((x, y) => Comparer<Xxx>.Default.Compare(y.Neto, x.Neto)); // unstable
}
其中Xxx
表示Neto
属性的声明(编译时(类型。如果.Neto
从不为 null 引用(包括 Xxx
是值类型的情况(,则这两个中的第一个(更简单(工作正常。
这些是下降的,因为我们交换了 lambda 箭头之后的x
和y
。
警告:不稳定意味着如果List<>
中的某些Items
具有同样小的.Neto
,则不知道它们的顺序会是什么。这不等同于前面的稳定示例。
如果您需要 Linq OrderByDescending
或需要稳定排序,您可以尝试以下方法(尽管它并不漂亮(:
private static void SortDesc(List<Items> items)
{
var tempList = items.OrderByDescending(x => x.Neto).ToList();
items.Clear();
items.AddRange(tempList);
}
除了 Clear
和 AddRange
之外,您还可以使用包含 items[i] = tempList[i]
的 for
循环显式复制列表条目。