C#中List移除值相同实例不同的结构体元素为何生效?
问题解答
没错,C#里值类型的相等判断默认就是基于值相等,而非实例身份——这也是值类型和引用类型最核心的区别之一。
具体原因:
- 值类型的默认相等逻辑:结构体作为值类型,默认的相等比较会逐一检查每个字段的数值是否完全一致。当你调用
List.Remove(T item)时,内部会使用EqualityComparer<T>.Default来做相等判断,对于值类型,这个默认比较器的逻辑就是值相等匹配。 - 你的场景匹配:你代码里的
Dir静态成员副本,和List<Dir>里的元素副本,只要它们的所有字段值都相同,Remove方法就能找到对应的元素并移除——不管是不是同一个实例,因为根本不关心实例“身份”,只看值。
自定义相等逻辑的方法:
如果需要改变这种默认的值相等行为,你可以:
- 重写结构体的
Equals(object)方法 - 实现
IEquatable<Dir>接口(更推荐,避免装箱操作) - 重载
==和!=运算符
举个简单示例:
public struct Dir : IEquatable<Dir> { public int Direction { get; } public Dir(int direction) => Direction = direction; public static Dir Incoming = new Dir(1); public static Dir Outgoing = new Dir(2); // 自定义相等判断逻辑 public bool Equals(Dir other) => Direction == other.Direction; public override bool Equals(object obj) => obj is Dir other && Equals(other); public override int GetHashCode() => Direction.GetHashCode(); public static bool operator ==(Dir left, Dir right) => left.Equals(right); public static bool operator !=(Dir left, Dir right) => !left.Equals(right); }
这个例子里的相等判断还是基于Direction字段值,如果你想改成其他规则,直接修改Equals方法内的逻辑即可。
内容的提问来源于stack exchange,提问作者Argo
相关产品推荐
相关产品推荐

