能否为非泛型BindingFilter与泛型BindingFilter<T>实现双向相等判断?
问题描述
我有两个类:非泛型的BindingFilter和泛型的BindingFilter<T>:
非泛型BindingFilter代码
public class BindingFilter { public object Value { get; set; } public string Member { get; set; } public BindingFilter(string member, object value) { Value = value ?? default!; Member = member; } public override bool Equals(object? obj) { if(obj == null) { return false; } if(obj is BindingFilter other) { return Member == other.Member && ( (Value is null && other.Value is null) || Equals(Value, other.Value) ); } return false; } }
泛型BindingFilter<T>代码
public class BindingFilter<T> { public T? Value { get; set; } public string Member { get; set; } public BindingFilter(string member, object? value) { Member = member; Value = (T?)value ?? default!; } public override bool Equals(object? obj) { if (obj is BindingFilter<T> other) { return Member == other.Member && Equals(Value, other.Value); } if (obj is BindingFilter untyped) { return Member == untyped.Member && Equals(Value, untyped.Value); } return false; } }
需要实现BindingFilter与BindingFilter<T>的双向相等判断,对应以下两个测试:
测试代码
[Fact] public void TypedBindingFilterEqualsUntypedBindingFilter() { var filter1 = new BindingFilter("ColumnName", string.Empty); var filter2 = new BindingFilter<string?>("ColumnName", string.Empty); Assert.True(filter2.Equals(filter1)); } [Fact] public void UntypedBindingFilterEqualsTypedBindingFilter() { var filter1 = new BindingFilter("ColumnName", string.Empty); var filter2 = new BindingFilter<string?>("ColumnName", string.Empty); Assert.True(filter1.Equals(filter2)); }
其中TypedBindingFilterEqualsUntypedBindingFilter测试通过,但UntypedBindingFilterEqualsTypedBindingFilter测试失败。请问是否可以实现该双向相等判断,使第二个测试通过?
解决方案
可以实现双向相等判断,问题根源是非泛型BindingFilter的Equals方法仅处理同类型实例,未识别泛型BindingFilter<T>对象。
修改非泛型BindingFilter的Equals方法,添加对泛型类型的处理逻辑:
public override bool Equals(object? obj) { if (obj == null) { return false; } // 处理非泛型同类型实例 if (obj is BindingFilter untypedOther) { return Member == untypedOther.Member && (Value == null && untypedOther.Value == null || Equals(Value, untypedOther.Value)); } // 识别并处理泛型BindingFilter<T>实例 var objType = obj.GetType(); if (objType.IsGenericType && objType.GetGenericTypeDefinition() == typeof(BindingFilter<>)) { // 通过反射获取泛型实例的Member和Value属性值 var memberProperty = objType.GetProperty(nameof(Member)); var valueProperty = objType.GetProperty(nameof(Value)); if (memberProperty == null || valueProperty == null) { return false; } var otherMember = (string)memberProperty.GetValue(obj)!; var otherValue = valueProperty.GetValue(obj); return Member == otherMember && Equals(Value, otherValue); } return false; }
修改后,第二个测试即可通过。核心要点:
- 泛型类已支持与非泛型类的相等判断,需让非泛型类反向支持泛型实例
- 利用反射识别泛型类型并读取属性,保证相等性的对称性(
a.Equals(b)与b.Equals(a)结果一致)
补充:重写GetHashCode
为保证相等对象的哈希码一致(避免哈希集合异常),建议同时重写两个类的GetHashCode方法:
非泛型BindingFilter的GetHashCode
public override int GetHashCode() { return HashCode.Combine(Member, Value); }
泛型BindingFilter<T>的GetHashCode
public override int GetHashCode() { return HashCode.Combine(Member, Value); }
内容的提问来源于stack exchange,提问作者dgo
相关产品推荐
相关产品推荐

