2009-05-30 5 views
0

Для ссылочного типа (класс), как 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); 
} 

Пожалуйста, внести изменения или опубликовать новую для как значения, так и ссылочные типы, которые я могу использовать в своих базовых типах (значение и ссылка), не задумываясь слишком много каждый раз, когда я реализую его снова.

EDIT: Это для неизменяемых типов.

+0

Erm ... В чем вопрос? – configurator

+0

Почему вы просите других людей сделать вашу работу за вас? Я могу понять, спрашивая совета, но просить нас выяснить, что проблема для вас - отличный способ закрыть ваш пост. – jrista

+0

Да, я на самом деле упомянул, что это был тип ref. –

ответ

3

this.GetType()! = Obj.GetType()

Это будет медленным. Используйте obj is Type.

ReferenceEquals Бесценен для ценностей, которые, как я полагаю, являются Point3.

Я также не стал бы проверять хэш-код в процедурах равенства.

4

Ну, прежде всего, не попадайте в ловушку создания хеш-кода, используя XOR в качестве оператора комбинации.

В противном случае, вы будете иметь следующие проблемы, где HC (х) означает «хэш-код объекта/значения х»:

HC(a,b) = HC(b,a) 
HC(a,a) = HC(b,b) = 0 

Вместо этого, выбрать что-то, что, по крайней мере принимает порядок эти значения учитываются следующим образом:

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 

Это будет, насколько это возможно, предварительное бронирование.

+0

Почему простое число? – configurator

+1

На самом деле вам придется спросить об этом Кнута. Все, что я знаю, это то, что он создает ценности, которые, как правило, менее подвержены столкновениям.По крайней мере (опять же, Кнут) вы должны выбрать два числа, которые являются взаимными, то есть не имеют общих факторов. –

2

Если вы действительно в производительности, а ваши значения x, y и z не меняются (по крайней мере, очень часто), в то время как вы проводите много сравнений, вы можете предварительно вычислить свой хэш-код. Затем используйте его очень рано во время вашего сравнения равенства.

Но самое лучшее в этом случае: используйте профайлер, чтобы найти реальное узкое место.

+1

Нет, вы не можете использовать хэш для надежной проверки равенства. –

+0

Если хеш-значения не равны, вы можете перестать сравнивать типы или что-то еще ... в большинстве случаев вы получите отрицательные удары ... и тогда хэш-код является очень быстрым механизмом – tanascius

2

Кроме того, если вы создаете свой собственный метод Equals, вы должны подумать о реализации IEquatable. Это дает хороший метод равенства для сравнения тот же типа, и часто вы можете сократить метод Equals (объект) к (для ссылочных типов):

public override Equals(object other) 
{ 
    Point3 otherP = other as Point3; 
    return otherP != null && Equals(otherP); // calls the Equals(Point3) method 
} 

Как быть немного лучше, это сокращает операция с ящиком, если тип является структурой, при условии, что реализация IEquatable неявна, код будет автоматически использовать типизированный метод Equals (Point3), а не использовать Equals (object), который включает операцию с ящиком (и, предположительно,)