按值从列表中删除项目

14
我有一个类对象列表并想删除其中一项,但它不起作用:

我有一个类对象列表并想要删除一项,但是它没有成功:

    class Person
    {
        public string name; 
        public Person(string s)
        {
            this.name = s;
        }
    }

    void ABC()
    {
        List<Person> newPersonList = new List<Person>();
        newPersonList.Add(new Person("A"));
        newPersonList.Add(new Person("B"));
        newPersonList.Add(new Person("C"));

        newPersonList.Remove(A);
        newPersonList.RemoveAt(1);
    }

RemoveAt(1) 可以工作并删除 ID 为 1 的项。

我认为 Remove(A) 应该删除值为“A”的项目,但这并没有起作用。有人能解释一下吗?正确的按值删除方式是什么?


1
你认为在 Remove(A); 应该发生什么?你没有声明 A。一般来说,你需要重写 Person 中的 Equals 或/和实现 IEquatable<Person> - Tim Schmelter
4个回答

29

按元素属性值从列表中删除的最简单方法:

newPersonList.RemoveAll(p => p.name == "A");

更好的方式是像这样更改Person

class Person : IEquatable<Person>
{
    public readonly string Name;
    public Person(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("name");
        Name = name;
    }
    public static implicit operator string(Person p)
    {
        return p.Name;
    }
    public static implicit operator Person(string name)
    {
        return new Person(name);
    }
    public bool Equals(Person other)
    {
        return Name.Equals(other.Name);
    }
}

然后这样使用:

var newPersonList = new List<Person>
{
    new Person("A"),
    new Person("B"),
    new Person("C")
};
newPersonList.Remove("A");

甚至可以像这样:

var newPersonList = new List<Person> { "A", "B", "C" };
newPersonList.Remove(new Person("A"));

3
他可以使用newPersonList.RemoveAll(p => p.name == "A")。你的方法需要扫描两次列表。但更好的方法是重写Person类中的Equals方法或让它实现IEquatable<Person>接口,这样Remove方法就能按预期工作了。 - Tim Schmelter
@TimSchmelter 平均复杂度对我的解决方案更好 =) - astef
1
@astef 不,你的解决方案并没有更低的平均复杂度。它做了更多的工作,而不是更少。 - Servy
@astef:另外,如果没有名字为“A”的人,您的方法会抛出错误。如果使用FirstOrDefault来防止删除null的人,则会删除一个人。您的第二种方法仅在偶然情况下起作用,因为引用是相互比较的。OP想要按名称进行比较。 - Tim Schmelter
@TimSchmelter 同意所有的意见。我在你的建议下编辑了我的答案。 - astef

1

所以你希望 .net 神奇地猜测你通过 "A" 字符串指的是字段 name?它应该如何推导出来呢?

如果你想通过键(在这种情况下是名称)操作事物,我建议你使用字典:

var dict = new Dictionary<string, Person>() {
   {"A", new Person("A")}
}

//and later

dict.Remove("A");

这甚至比那更神奇,因为它只是 A 而不是字符串 "A" - juharr
我认为他真正想表达的是字符串,否则只有A没有任何意义。 - Andrey
如果您想使类可比较,您会使用字典吗?您只需要提供一个用于确定两个对象是否相等的方法,即“Equals”。 - Tim Schmelter
@TimSchmelter 我没有说可比较。我是说,如果您想通过某个字段值检索对象,则可以将其用作键并使用字典。 - Andrey

-1

你没有声明A。要执行 newPersonList.Remove(A);

你需要声明一个名为Person A的对象并将其添加到newPersonList中

Person A = new Person("A");
newPersonList.Add(A);

-1

就像其他人说的那样,“A是什么?”。如果它是一个包含Person的变量,那么这将起作用。

void ABC()
{
    var A = new Person("A");
    var B = new Person("B");
    var C = new Person("C");
    List<Person> newPersonList = new List<Person>();
    newPersonList.Add(A);
    newPersonList.Add(B);
    newPersonList.Add(C);

    newPersonList.Remove(A);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接