For a reference type (class) like Point3 (for example), is this an overkill, lacking:
对于像Point3这样的引用类型(类)(例如),这是一种过度杀伤,缺乏:
#region System.Object Members
public override bool Equals ( object obj )
{
//return this == ( Point3 ) obj;
if ( obj == null )
{
return false;
}
if ( this.GetType ( ) != obj.GetType ( ) )
{
return false;
}
return this.Equals ( ( Point3 ) obj );
}
public override int GetHashCode ( )
{
return this.X.GetHashCode ( ) ^ this.Y.GetHashCode ( ) ^ this.Z.GetHashCode ( );
}
public override string ToString ( )
{
return String.Format ( "[{0}, {1}, {2}]", this.X, this.Y, this.Z );
}
#endregion
#region IEquatable<Point3> Members
public bool Equals ( Point3 other )
{
if ( other == null )
{
return false;
}
if ( ReferenceEquals ( this, other ) )
{
return true;
}
if ( this.GetHashCode ( ) != other.GetHashCode ( ) )
{
return false;
}
if ( !base.Equals ( other ) )
{
return false;
}
return this == other;
}
#endregion
public static bool operator == ( Point3 v0, Point3 v1 )
{
return ( v0.X.IsEqual ( v1.X ) ) && ( v0.Y.IsEqual ( v1.Y ) ) && ( v0.Z.IsEqual ( v1.Z ) );
}
public static bool operator != ( Point3 v0, Point3 v1 )
{
return !( v0 == v1 );
}
Please make adjustments or post a new one for both value and reference types, that I can use in my base types (value and reference) without thinking too much every time I implement it again.
请为我的基本类型(值和参考)中的值和引用类型进行调整或发布新的值,而不必在每次重新实现时都考虑太多。
EDIT: This is for immutable types.
编辑:这是不可变类型。
4 个解决方案
#1
Well, first of all, don't fall into the trap of producing a hash code using XOR as your combination operator.
好吧,首先,不要陷入使用XOR作为组合运算符生成哈希码的陷阱。
Otherwise, you'll have the following problems, where HC(x) means "the hash code of object/value x":
否则,您将遇到以下问题,其中HC(x)表示“对象/值x的哈希码”:
HC(a,b) = HC(b,a)
HC(a,a) = HC(b,b) = 0
Instead, opt for something that at least takes the order of the values into account, like the following:
相反,选择至少考虑值的顺序的东西,如下所示:
hashcode = 23 // prime number
for each sub-value of the object, do:
hashcode = hashcode * 31 // another prime number
hashcode = hashcode + the hashcode of the sub-value
This will preserver ordering, as much as possible.
这将尽可能地保留订购。
#2
this.GetType ( ) != obj.GetType ( )
this.GetType()!= obj.GetType()
That will be slow. Use obj is Type
rather.
那将是缓慢的。使用obj是Type而不是。
ReferenceEquals
is pointless for valuetypes, which I assume Point3 is.
ReferenceEquals对于valuetypes是没有意义的,我假设Point3是。
I would also not bother with the hash code check in equality procedures.
我也不打扰在等式过程中使用哈希码检查。
#3
If you are really into performance and your values x, y and z do not change (at least very often), while you do a lot of comparisons, you could pre-calculate your hashcode. Then use it very early during your equality-comparison.
如果你真的进入了性能并且你的值x,y和z没有改变(至少经常),当你进行大量的比较时,你可以预先计算你的哈希码。然后在平等比较期间尽早使用它。
But the best in this case is: use a profiler to find the real bottleneck.
但在这种情况下最好的是:使用分析器来找到真正的瓶颈。
#4
ALso, if you are creating your own Equals method, you should think about implementing IEquatable. This gives you a nice equality method to compare the same type, and often you can cut down the Equals(object) method to (for reference types):
另外,如果要创建自己的Equals方法,则应考虑实现IEquatable。这为您提供了一个很好的相等方法来比较相同的类型,通常可以将Equals(object)方法减少为(对于引用类型):
public override Equals(object other)
{
Point3 otherP = other as Point3;
return otherP != null && Equals(otherP); // calls the Equals(Point3) method
}
As well as being a bit nicer, this cuts down a box operation if the type is a struct - provided the IEquatable implementation is implicit, code will automatically use the typed Equals(Point3) method, rather than using Equals(object) that involves a box operation (and presumably an unbox actually inside that method)
除了更好一点,如果类型是结构,这会减少一个盒子操作 - 如果IEquatable实现是隐式的,代码将自动使用类型化的Equals(Point3)方法,而不是使用涉及一个的Equals(对象)框操作(实际上可能是该方法中的unbox)
#1
Well, first of all, don't fall into the trap of producing a hash code using XOR as your combination operator.
好吧,首先,不要陷入使用XOR作为组合运算符生成哈希码的陷阱。
Otherwise, you'll have the following problems, where HC(x) means "the hash code of object/value x":
否则,您将遇到以下问题,其中HC(x)表示“对象/值x的哈希码”:
HC(a,b) = HC(b,a)
HC(a,a) = HC(b,b) = 0
Instead, opt for something that at least takes the order of the values into account, like the following:
相反,选择至少考虑值的顺序的东西,如下所示:
hashcode = 23 // prime number
for each sub-value of the object, do:
hashcode = hashcode * 31 // another prime number
hashcode = hashcode + the hashcode of the sub-value
This will preserver ordering, as much as possible.
这将尽可能地保留订购。
#2
this.GetType ( ) != obj.GetType ( )
this.GetType()!= obj.GetType()
That will be slow. Use obj is Type
rather.
那将是缓慢的。使用obj是Type而不是。
ReferenceEquals
is pointless for valuetypes, which I assume Point3 is.
ReferenceEquals对于valuetypes是没有意义的,我假设Point3是。
I would also not bother with the hash code check in equality procedures.
我也不打扰在等式过程中使用哈希码检查。
#3
If you are really into performance and your values x, y and z do not change (at least very often), while you do a lot of comparisons, you could pre-calculate your hashcode. Then use it very early during your equality-comparison.
如果你真的进入了性能并且你的值x,y和z没有改变(至少经常),当你进行大量的比较时,你可以预先计算你的哈希码。然后在平等比较期间尽早使用它。
But the best in this case is: use a profiler to find the real bottleneck.
但在这种情况下最好的是:使用分析器来找到真正的瓶颈。
#4
ALso, if you are creating your own Equals method, you should think about implementing IEquatable. This gives you a nice equality method to compare the same type, and often you can cut down the Equals(object) method to (for reference types):
另外,如果要创建自己的Equals方法,则应考虑实现IEquatable。这为您提供了一个很好的相等方法来比较相同的类型,通常可以将Equals(object)方法减少为(对于引用类型):
public override Equals(object other)
{
Point3 otherP = other as Point3;
return otherP != null && Equals(otherP); // calls the Equals(Point3) method
}
As well as being a bit nicer, this cuts down a box operation if the type is a struct - provided the IEquatable implementation is implicit, code will automatically use the typed Equals(Point3) method, rather than using Equals(object) that involves a box operation (and presumably an unbox actually inside that method)
除了更好一点,如果类型是结构,这会减少一个盒子操作 - 如果IEquatable实现是隐式的,代码将自动使用类型化的Equals(Point3)方法,而不是使用涉及一个的Equals(对象)框操作(实际上可能是该方法中的unbox)