C# 中的“List.Remove”不删除项目?

Posted

技术标签:

【中文标题】C# 中的“List.Remove”不删除项目?【英文标题】:"List.Remove" in C# does not remove item? 【发布时间】:2021-05-28 00:37:46 【问题描述】:

您好,我如何从通用列表中删除项目,这是我的代码,我正在尝试正确执行,但我不知道我在哪里犯了错误;/

Users us_end = new Users();
foreach (var VARIABLE in ((List<Users>)Application["Users_On"]))

    if(VARIABLE.Id == (int)Session["Current_Id"])
    
        us_end.Name = VARIABLE.Name;
        us_end.Id = VARIABLE.Id;
        us_end.Data = VARIABLE.Data;
    

List<Users> us = ((List<Users>)Application["Users_On"]);
us.Remove(us_end);
Application["Users_On"] = us;

【问题讨论】:

嗯,有什么不符合预期? (要使Remove 工作,该项目需要正确实施Equals)。 这并没有多大意义:您正在覆盖您在 foreach 中创建的每个用户对象.. 另外,您将Application["Users_On"] 转换为List&lt;Users,然后将其设置为User。这显然是错误的,如果您希望该代码继续“工作”,则不能两者兼而有之 【参考方案1】:

你必须得到相同的对象来删除,而不是一个副本。

Users us_end;

foreach (var VARIABLE in ((List<Users>)Application["Users_On"]))

    if(VARIABLE.Id == (int)Session["Current_Id"])
    
       us_end = (Users)VARIABLE;
       break;
    


if (us_end != null)

    List<Users> us = ((List<Users>)Application["Users_On"]);
    us.Remove(us_end);
    Application["Users_On"] = us;

编辑:

只是为了澄清这里的地址,正如 pst 指出的那样,您还可以实现 IEquatable 接口和一些覆盖,例如 Groo 的答案以使其工作,但我认为这在这个特定主题上是矫枉过正的。将此作为最常见的做法,但要明确表示也可以从列表中删除项目,即使它们是不同的实例,甚至是使用类似技术的不同对象。

参考:http://msdn.microsoft.com/en-us/library/ms131187.aspx

【讨论】:

那你为什么没有发布正确的答案呢?如果你认为你有心情解释比较的覆盖只是为了从列表中删除一个对象,那么就这样做。我理解你的观点,但是请你自己回答并解释一下,这样他就可以把它标记为正确的,而不是落在我身上。 因为答案是“正确的”,包括这个,只是 [最初] 误导 :) 尼特:它不需要将 IEquatable 实现为 object.Equals(object) - 记住这一点是多态的! ——仍然可以使用。我使用Remove 和其他 Equals-requiring 方法,只是在我为我的类型定义的相等性下“期望它工作”。也就是说,我希望a.Equals(b) 的工作方式与l.Add(a); l.Remove(b) 的工作方式相同,反之亦然。【参考方案2】:

默认情况下,在 .NET 中通过引用比较对象相等性(除非覆盖 Equals,否则每个对象都继承自 object.Equals)。如果您希望Remove 方法找到您的对象,则不能传递新对象。

最简单的方法是找到具有所需属性的实际对象,然后将其删除:

var id = (int)Session["Current_Id"];
var list = (List<Users>)Application["Users_On"];  

// find the exact item to remove.
var itemToRemove = list.FirstOrDefault(u => u.Id = id);

// if found, remove it
if (itemToRemove != null)

    list.Remove(itemToRemove);

【讨论】:

但是Equals 是虚拟的。这对我来说没有意义。 @pst:一个虚方法,除非显式重写,其行为类似于基类中定义的行为。 Object.Equals 通过引用进行比较。 更新后我可以接受(之前是错的,因为不知道用户的定义)。【参考方案3】:

您正在创建一个 Users 对象 - 这与 Application["Users_On"] 中已有的任何对象都不相同(它将具有不同的引用),因此不会被删除。

这假设Equals 和/或IEquatable&lt;T&gt; 没有在Users 中被覆盖/实现。

List<Users> us = ((List<Users>)Application["Users_On"]);
Users us_end = us.Where(u => u.Id == (int)Session["Current_Id"]).FirstOrDefault();
us.Remove(us_end);
Application["Users_On"] = us;

顺便说一句 - 你的变量命名不是很好 - 使用更具描述性的名称。

【讨论】:

是的,它适用于相等,默认情况下,对于对象,相等是通过检查引用来实现的... @pst - 引用类型将是引用相等。 @Oded class Users override Equals ?? -1 因为这无法解决“此方法使用默认相等比较器 EqualityComparer 确定相等。默认为 T,即列表中值的类型。” msdn.microsoft.com/en-us/library/cd666k3e.aspx 和“默认属性检查类型 T 是否实现 System.IEquatable 接口,如果是,则返回使用该实现的 EqualityComparer。否则,它返回使用覆盖的 EqualityComparer由 T 提供的 Object.Equals 和 Object.GetHashCode。” msdn.microsoft.com/en-us/library/ms224763.aspx 也就是说,“它将有不同的引用”并不意味着Remove 将不起作用。【参考方案4】:

关于:

List<Users> us = ((List<Users>)Application["Users_On"]);
Users us_end = us.First(x => x.ID == (int)Session["Current_Id"]);
us.Remove(us_end);
Application["Users_On"] = us;

【讨论】:

【参考方案5】:

通过在 remove 语句中查找项目来将其删除,而不是通过额外的副本:

List<Users> us = ((List<Users>)Application["Users_On"]);
us.Remove(us.FirstOrDefault(u => u.ID == (int)Session["Current_Id"]));
Application["Users_On"] = us;

【讨论】:

【参考方案6】:

正如有人在前面的答案中所说:对象相等性在 .NET 中通过引用进行比较。 但是您可以通过简单地将 List 中的元素 T 从类转换为结构来从类和结构之间的差异中受益。

【讨论】:

以上是关于C# 中的“List.Remove”不删除项目?的主要内容,如果未能解决你的问题,请参考以下文章

C# 根据 条件判断删除List<Warehouse>某个对象

在颤动中使用 list.remove(element) 时未在列表中删除项目

C# List集合,在调用list.remove方法删除某一元素后触发事件,请问这个事件怎么写?

list.remove(x) 删除超过此列表中的对象[重复]

List 集合 remove 对象时出现 ConcurrentModificationException

怎样从Arraylist中删除一个元素