2015-07-20 9 views
6

Kiedy przesłanianie metody Equals() The MSDN recommends this:Przesłanianie równań(): czy zerowe porównanie jest zbędne przy wywołaniu base.Equals()?

class Point: Object { 
    protected int x, y; 

    public Point(int X, int Y) { 
     this.x = X; 
     this.y = Y; 
    } 

    public override bool Equals(Object obj) { 

     //Check for null and compare run-time types. 
     if (obj == null || GetType() != obj.GetType()) return false; 

     Point p = (Point)obj; 

     return (x == p.x) && (y == p.y); 
    } 
} 

Ale jeśli wiemy, że podklasa dziedziczy bezpośrednio od Object, następnie jest następujący odpowiednik? Zwróć uwagę na !base.Equals() połączenia:

class Point: Object { 
    protected int x, y; 

    public Point(int X, int Y) { 
     this.x = X; 
     this.y = Y; 
    } 

    public override bool Equals(Object obj) { 

     if (!base.Equals(obj) || GetType() != obj.GetType()) return false; 

     Point p = (Point)obj; 

     return (x == p.x) && (y == p.y); 
    } 
} 
+0

Nie, ponieważ '! Base.Equals (obj)' zwróci 'true', co spowoduje, że metoda równań zwróci wartość" false ", jeśli nie są one dokładnie tymi samymi obiektami. Jeśli to ten sam obiekt, to reszta czeku gwarantuje powodzenie. Zasadniczo sprawi, że twoje przesłonięcie nic nie zmieni. – Rob

+0

@Rob - jeśli '! Base.Equals (obj)' zwraca wartość true, to * chcesz *, aby zwrócić wartość false. –

+0

'base.Equals (obj)' sprawdzi, czy bieżący obiekt i obiekt 'obj' są * dokładnie * tym samym obiektem. Oznacza to, że są one wskaźnikami do dokładnie tego samego obiektu w pamięci. Jeśli są to różne obiekty, twoi równi natychmiast zwrócą fałsz. Jeśli * są * tym samym obiektem, to zarówno GetType() == obj.GetType() 'jak i' (x == px) && (y == py) 'są gwarantowane, aby zwrócić' true' – Rob

Odpowiedz

5

W przypadku this odniesienia jest null masz rację, że kontrola może być (ale nie wydają się być gwarantowane) zbędne, jak to widać w RuntimeHelpers.Equals realizacji cyt this answer.

Jednak kontrola !base.Equals(obj) złamie twój Equals. Gdy odwołania nie są null - !base.Equals, będą również dawać true dla dowolnych różnych wartości 10 nie tylko dla wartości null.

Scenariusz gdy idzie źle to na przykład:

Point x = new Point(1,2); 
Point y = new Point(1,2); 

Console.WriteLine(x.Equals(y)); // will print 'False' 

Nawet x i y są równe pod względem logiki biznesowej, są one różne obiekty tak base.Equal zwraca false.

+0

Oh! Teraz rozumiem. To dość znaczący błąd semantyczny! – kdbanman

+0

Czy istnieje przypadek, gdy 'this' ma wartość NULL w C#, z wyjątkiem sytuacji, gdy jest to odręczny IL? Nie sądzę, żeby tak było, ale mogę się mylić – Rob

+1

@BartoszKP Jak dokładnie? Nie można wywołać metody elementu na obiekcie zerowym za pomocą metody "MethodInfo.Invoke", a zdecydowanie nie można wykonać 'MyTest t = null; t.Equals (null) '. – Rob