Roman Czarnecki

Roman Czarnecki Student, Wyższa
Szkoła Informatyki
Stosowanej i
Zarządzan...

Temat: Equals() i GetHashCode() w klasie Generycznej.

Czy istnieje możliwość zaimplementowania tych metod w bazowej klasie generycznej? Zależy mi na tym by porównanie obiektów oraz wyciąganie hashy odbywało się poprzez właściwości klasy dziedziczącej po klasie generycznej.
Obiekt generyczny w klasie bazowej nic nie wie o właściwościach i generalnie wiem, że mogę wykorzystać metodę t.GetType().GetProperties();.
Jak można rozegrać problem porównania obiektów? Chodzi mi o to, że słowa "this" nie mogę użyć w klasie generycznej.

Czy jednak muszę implementować te dwie metody oddzielnie dla każdej klasy pochodnej?

Z góry dzięki za info w tej sprawie.

Roman Czarnecki

konto usunięte

Temat: Equals() i GetHashCode() w klasie Generycznej.

Powiedz co chcesz osiągnąć, najlepiej pokazując przykład użycia obiektów twojej nowej klasy w kodzie C#.
Może się okazać, że wszystko co potrzebujesz to odwołania do IEquatable<T>.

konto usunięte

Temat: Equals() i GetHashCode() w klasie Generycznej.

`Piotr Sowa edytował(a) ten post dnia 12.02.12 o godzinie 15:35

konto usunięte

Temat: Equals() i GetHashCode() w klasie Generycznej.

Maciek dobrze radzi. Z ciekawości spróbowałem napisać to przez refleksję i GetProperties(). Da się dla property typu value czy string, ale może z tego wyniknąć trochę kłopotów np. przy kolekcjach czy typach złożonych. Jeżeli lubisz ryzyko, masz mocne nerwy i/lub "certyfikaty z holiłudu" to:


public class BaseObject<T>
{
private readonly T _foo;

public BaseObject(T foo)
{
this._foo = foo;
}

public T Foo()
{
return this._foo;
}

public override int GetHashCode()
{
var builder = new StringBuilder();
var props = this.GetType().GetProperties();
foreach (var prop in props)
{
builder.Append(prop.Name + prop.GetValue(this, null).GetHashCode());
}

return builder.ToString().GetHashCode();
}

public override bool Equals(object obj)
{
var props = this.GetType().GetProperties();
foreach (var prop in props)
{
var objprop = obj.GetType().GetProperty(prop.Name);
if (objprop == null)
{
return false;
}

if (prop.GetValue(this, null).GetHashCode() != objprop.GetValue(obj, null).GetHashCode())
{
return false;
}
}

return true;
}
}
Jarek D. edytował(a) ten post dnia 13.10.09 o godzinie 00:35
Roman Czarnecki

Roman Czarnecki Student, Wyższa
Szkoła Informatyki
Stosowanej i
Zarządzan...

Temat: Equals() i GetHashCode() w klasie Generycznej.

Otóż background jest taki, że zależy mi w warstwie modelu (obiekty zmapowane z bazy) dla każdej klasy HashCode oraz porównanie odbywało się na podstawie tylko i wyłącznie pól pomijając asocjacje (relacje) do innych obiektów). Linq miał z tym problem i wykonując operacje na zbiorach z wyciągniętych danych (Intersect, Distinct, Union) zwracało zero rekordów i trzeba było napisać własny comparer do każdej z mapowanych z klas.
Teraz bawię się NHibernate'm, stworzyłem klasę bazową generyczną modelu ModelBase<T> where T : class, i ona ma w sobie właściwość Id, pozostałe klasy mapujące po niej dziedziczą. Zastanawiałem się czy jest możliwa własna implementacja equals() i gethashcode() w tej bazowej klasie? I tu mam właśnie problem bo klasa generyczna nie wie nic o właściwościach klas pochodnych. Pytam się bo też nie mam doświadczenia jeżeli chodzi o NHibernate'a, a z tego co wiem, że kiedy przerzucamy obiektami między sesjami NHibernate'a, to nawet jeśli wyciągniemy dwa te same wiersze przez różne sesje to NHibernate nie daje gwarancji na poprawne działanie Equals() i GetHashCode() (Działa tylko w obrębie jednej sesji).

Może też źle kombinuję. Ale jeżeli ktoś miał z tym zjazdy i wie jak ten suchar rozgryźć to z góry dziękuję :).

konto usunięte

Temat: Equals() i GetHashCode() w klasie Generycznej.

Jeżeli bawisz się z NHibernate - to polecam projekt Castle.ActiveRecord i blog guru NHibernate czyli Ayende

http://ayende.com/Blog/archive/2007/03/20/Plain-old-.N...

Co do twojego problemu - to tak można to zrobić w klasie bazowej i użyć Id - do wykonywania porównań. Musisz napisać swoje metody Equals i GetHashCode.

A co z obiektami nie są zapisane zapytasz - no wtedy ustalamy, że ich Id jest równe 0 i w metodzie Equals używamy metody ReferenceEquals - czyli sprawdzamy czy to nie są TE same obiekty (http://msdn.microsoft.com/en-us/library/system.object_.... Dzięki temu załatwiamy przypadek kiedy obiekt nie jest jeszcze w bazie.

Co do sesji - to masz rację - przenoszenie obiektów pomiędzy sesjami nie jest takie proste, ale jak napiszesz metody Equals i GetHashCode według tego wzoru to można to zrobić.
Roman Czarnecki

Roman Czarnecki Student, Wyższa
Szkoła Informatyki
Stosowanej i
Zarządzan...

Temat: Equals() i GetHashCode() w klasie Generycznej.

Dzięki za pomoc wszystkim. Udało mi się to załatwić.

W Equals() zrobiłem tak, że porównywany jest typ klasy mapującej i Id (żeby nie było tak, że Faktura i pozycja faktury o Id 1 są tym samym obiektem :)) Dzięki za info na temat ActiveRecord będę musiał kiedyś obadać sprawę.

Pozdrawiam.

Podobne tematy


Następna dyskusja:

Object.Equals




Wyślij zaproszenie do