重载==仅包含字符串属性的类的运算符
本文关键字:运算符 属性 字符串 包含 重载 | 更新日期: 2023-09-27 18:00:43
在只包含字符串属性的类上重载相等运算符的最佳(最优雅或性能最好)方法是什么?
示例:
class MagicClass
{
public string FirstAttribute { get; set; }
public string SecondAttribute { get; set; }
public string ThirdAttribute { get; set; }
public string FourthAttribute { get; set; }
public string FifthAttribute { get; set; }
}
我知道如何超载运营商本身,然而,我想知道以下几点:
- 有没有一种方法可以优雅地比较这两个对象(例如,不必编写包含所有属性的相互比较的
if
语句 - 在这种情况下,
GetHashCode()
方法的良好实现是什么
这样做怎么样,只需创建所有属性的数组和一个循环。
internal class MagicClass
{
public string FirstAttribute { get; set; }
public string SecondAttribute { get; set; }
public string ThirdAttribute { get; set; }
public string FourthAttribute { get; set; }
public string FifthAttribute { get; set; }
private string[] AllProperties//Array of all properties
{
get
{
return new[]
{
FirstAttribute,
SecondAttribute,
ThirdAttribute,
FourthAttribute,
FifthAttribute
};
}
}
protected bool Equals(MagicClass other)
{
var thisProps = this.AllProperties;
var otherProps = other.AllProperties;
return thisProps.SequenceEqual(otherProps);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((MagicClass) obj);
}
public override int GetHashCode()
{
unchecked
{
var thisProps = this.AllProperties;
int hashCode = 0;
foreach (var prop in thisProps)
{
hashCode = (hashCode * 397) ^ (prop != null ? prop.GetHashCode() : 0);
}
return hashCode;
}
}
}
然后,您可以在运算符重载中调用Equals
方法。如果你懒得创建AllProperties
数组,你可以使用Reflection
,但IMO反射在这里太过分了。
并不是说这是"最好的"或最优雅的解决方案,但我倾向于使用数组和索引初始值设定项,使用枚举,这样我就可以重用get和set逻辑,在这种情况下,还可以重置哈希码以进行快速的第一次比较。枚举的优点是,添加属性时不必重新检查比较逻辑,并且可以防止诉诸反射的开销。
class MagicClass
{
string[] Values = new string[Enum.GetValues(typeof(MagicClassValues)).Length];
public string this[MagicClassValues Value] //and/or a GetValue/SetValue construction
{
get
{
return Values[(int)Value];
}
set
{
Values[(int)Value] = value;
hash = null;
}
}
int? hash; //buffered for optimal dictionary performance and == comparisson
public override int GetHashCode()
{
if (hash == null)
unchecked
{
hash = Values.Sum(s => s.GetHashCode());
}
return hash.Value;
}
public static bool operator ==(MagicClass v1, MagicClass v2) //used == operator, in compliance to the question, but this would be better for 'Equals'
{
if(ReferenceEquals(v1,v2))return true;
if(ReferenceEquals(v1,null) || ReferenceEquals(v2,null) || v1.GetHashCode() != v2.GetHashCode())return false;
return v1.Values.SequenceEqual(v2.Values);
}
public static bool operator !=(MagicClass v1, MagicClass v2)
{
return !(v1 == v2);
}
//optional, use hard named properties as well
public string FirstAttribute { get { return this[MagicClassValues.FirstAttribute]; } set { this[MagicClassValues.FirstAttribute] = value; } }
}
public enum MagicClassValues
{
FirstAttribute,
SecondAttribute,
//etc
}