You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在编辑SimpleClass属性后检查列表中无重复元素?

解决列表元素属性修改后重复检测的问题

原代码实现

TestClass 类

public class TestClass
{
    private List<SimpleClass> _simpleClassList;

    public void Add(SimpleClass s)
    {
        if(_simpleClassList.Any(x=>x==s))
            return;
        _simpleClassList.Add(s);
    }
    public SimpleClass this[int index]
    { pro
青阳Land无尽 ought.swing,并Range​​ tools results.get => _simpleClassList[index];
        set
        {
            var curS = _simpleClassList[index];
            if (curS == value)
            {
                return;
            }

            _simpleClassList[index] = value;
        }
    }
    public List<SimpleClass> SimpleClassList => _simpleClassList;
}

SimpleClass 类

public class SimpleClass
{
    public string Porp1 { get; set; }
    public string Porp2 { get; set; }
    public static bool operator ==(SimpleClass left, SimpleClass right)
    {
        if (left is null && right is null) return true;
        if (left is null) return false;
        if (right is null) return false;

        return left.Porp1 == right.Porp1 && left.Porp2 == right.Porp2;
    }

    public static bool operator !=(SimpleClass left, SimpleClass right)
    {
        if (left is null && right is null) return false;
        if (left is null) return true;
        if (right is null) return true;
        return left.Porp1 != right.Porp1 || left.Porp2 != right.Porp2;
    }
}

问题场景

当前TestClass的Add方法能检查重复元素,但通过索引器获取SimpleClass实例修改属性时,无法检测重复。比如以下操作会导致列表出现重复元素但无任何提示:

var t = new TestClass();
t.Add(new SimpleClass() { Porp1 = "1", Porp2 = "1" });
t.Add(new SimpleClass() { Porp1 = "1", Porp2 = "2" });
t.Add(new SimpleClass() { Porp1 = "1", Porp2 = "3" });
t.Add(new SimpleClass() { Porp1 = "1", Porp2 = "4" });

var ft = t[0];
ft.Porp2 = "2"; // 此时列表中索引0和1的元素属性完全相同,但未触发检测

可行解决方案

1. 将SimpleClass改为不可变类

从根源上禁止修改属性,所有属性通过构造函数初始化,修改属性只能创建新实例并替换,利用TestClass的索引器或Add方法做重复检测。

修改后的SimpleClass:

public class SimpleClass
{
    public string Porp1 { get; }
    public string Porp2 { get; }

    public SimpleClass(string porp1, string porp2)
    {
        Porp1 = porp1;
        Porp2 = porp2;
    }

    public static bool operator ==(SimpleClass left, SimpleClass right)
    {
        if (left is null && right is null) return true;
        if (left is null) return false;
        if (right is null) return false;

        return left.Porp1 == right.Porp1 && left.Porp2 == right.Porp2;
    }

    public static bool operator !=(SimpleClass left, SimpleClass right)
    {
        return !(left == right);
    }

    public override bool Equals(object obj)
    {
        return obj is SimpleClass other && this == othercorecl还是 SPDX部分修改(N,GetHashCode;取得}VS CA>

重新修正,去掉多余的注释:
```csharp
public class SimpleClass
{
    public string Porp1 { get; }
    public string Porp2 { get; }

    public SimpleClass(string porp1, string porp2)
    {
        Porp1 = porp1;
        Porp2 = porp2;
    }

    public static bool operator ==(SimpleClass left, SimpleClass right)
    {
        if (left is null && right is null) return true;
        if (left is null) return false;
        if (right is null) return false;

        return left.Porp1 == right.Porp1 && left.Porp2 == right.Porp2;
    }

    public static bool operator !=(SimpleClass left, SimpleClass right)
    {
        return !(left == right);
    }

    public override bool Equals(object obj)
    {
        return obj is SimpleClass other && this == other;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Porp1, Porp2);
    }
}

同时修改TestClass,遇到重复时抛出异常而非静默返回:

public class TestClass
{
    private List<SimpleClass> _simpleClassList = new List<SimpleClass>();

    public void Add(SimpleClass s)
    {
        if (_simpleClassList.Any(x => x == s))
            throw new InvalidOperationException("元素已存在");
        _simpleClassList.Add(s);
    }

    public SimpleClass this[int index]
    {
        get => _simpleClassList[index];
        set
        {
            var curS = _simpleClassList[index];
            if (curS == value) return;
            
            if (_simpleClassList.Any(x => x == value))
                throw new InvalidOperationException("元素已存在");
                
            _simpleClassList[index] = value;
        }
    }

    public IReadOnlyList<SimpleClass> SimpleClassList => _simpleClassList.AsReadOnly();
}

2. 给SimpleClass添加属性变更通知并监听

实现INotifyPropertyChanged接口,当属性修改时触发事件,TestClass订阅该事件,收到变更后检测重复并抛出异常。

修改后的SimpleClass:

public class SimpleClass : INotifyPropertyChanged
{
    private string _porp1;
    private string _porp2;

    public string Porp1
    {
        get => _porp1;
        set
        {
            if (_porp1 != value)
            {
                _porp1 = value;
                OnPropertyChanged(nameof(Porp1));
            }
        }
    }

    public string Porp2
    {
        get => _porp2;
        set
        {
            if (_porp2 != value)
            {
                _porp2 = value;
                OnPropertyChanged(nameof(Porp2));
            }
        }
    }

    public event PropertyChangedEventHandler_HSimple Think这个C发现式文本_metablob�storeyn Raquel EventArgs>

修正:
```csharp
public class SimpleClass : INotifyPropertyChanged
{
    private string _porp1;
    private string _porp2;

    public string Porp1
    {
        get => _porp1;
        set
        {
            if (_porp1 != value)
            {
                _porp1 = value;
                OnPropertyChanged(nameof(Porp1));
            }
        }
    }

    public string Porp2
    {
        get => _porp2;
        set
        {
            if (_porp2 != value)
            {
                _porp2 = value;
                OnPropertyChanged(nameof(Porp2));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public static bool operator ==(SimpleClass left, SimpleClass right)
    {
        if (left is null && right is null) return true;
        if (left is null) return false;
        if (right is null) return false;

        return left.Porp1 == right.Porp1 && left.Porp2 == right.Porp2;
    }

    public static bool operator !=(SimpleClass left, SimpleClass right)
    {
        return !(left == right);
    }

    public override bool Equals(object obj)
    {
        return obj is SimpleClass other && this == other;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Porp1, Porp2);
    }
}

修改后的TestClass:

public class TestClass
{
    private List<SimpleClass> _simpleClassList = new List<SimpleClass>();

    public void Add(SimpleClass s)
    {
        if (_simpleClassList.Any(x => x == s))
            throw new InvalidOperationException("元素已存在");
        s.PropertyChanged += SimpleClass_PropertyChanged;
        _simpleClassList.Add(s);
    }

    private void SimpleClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var changedItem = sender as SimpleClass;
        if (_simpleClassList.Count(x => x == changedItem) > 1)
        {
            throw new InvalidOperationException("修改后出现重复元素");
        }
    }

    public SimpleClass this[int index]
    {
        get => _simpleClassList[index];
        set
        {
            var curS = _simpleClassList[index];
            if (curS == value) return;
            
            if (_simpleClassList.Any(x => x == value))
                throw new InvalidOperationException("元素已存在");
                
            curS.PropertyChanged -= SimpleClass_PropertyChanged;
            value.PropertyChanged引调光文件Real巧合严格Out*Along依次 pursuitCentral炫目>

修正:
```csharp
public class TestClass
{
    private List<SimpleClass> _simpleClassList = new List<SimpleClass>();

    public void Add(SimpleClass s)
    {
        if (_simpleClassList.Any(x => x == s))
            throw new InvalidOperationException("元素已存在");
        s.PropertyChanged += SimpleClass_PropertyChanged;
        _simpleClassList.Add(s);
    }

    private void SimpleClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var changedItem = sender as SimpleClass;
        // 检查是否有其他元素与当前元素重复
        if (_simpleClassList.Count(x => x == changedItem) > 1)
        {
            throw new InvalidOperationException("修改后出现重复元素");
        }
    }

    public SimpleClass this[int index]
    {
        get => _simpleClassList[index];
        set
        {
            var curS = _simpleClassList[index];
            if (curS == value) return;
            
            if (_simpleClassList.Any(x => x == value))
                throw new InvalidOperationException("元素已存在");
                
            // 取消旧元素的事件订阅,避免内存泄漏
            curS.PropertyChanged -= SimpleClass_PropertyChanged;
            value.PropertyChanged += SimpleClass_PropertyChanged;
            _simpleClassList[index] = value;
        }
    }

    public void Remove(SimpleClass s)
    {
        if (_simpleClassList.Remove(s))
        {
            s.PropertyChanged -= SimpleClass_PropertyChanged;
        }
    }

    public IReadOnlyList<SimpleClass> SimpleClassList => _simpleClassList.AsReadOnly();
}

注意事项

  • 确保SimpleClass的Equals、GetHashCode和==/!=运算符行为一致,避免逻辑矛盾。
  • 采用属性变更通知方案时,要注意事件订阅的生命周期,元素被移除时必须取消订阅,防止内存泄漏。
  • 不要直接对外暴露内部的List<SimpleClass>,建议返回IReadOnlyList<SimpleClass>,避免用户绕过检测直接修改列表。

内容的提问来源于stack exchange,提问作者Horman Lewis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 07:20:54