Porównywanie obiektów

0

W języku C# muszę stworzyć klasę Słownik<K,V> (nie wykorzystując klas bibliotecznych). Implementacja polega na tym, że Slownik<K,V> przechowuje pary elementów, gdzie pierwszym elementem pary jest klucz, a drugim wartość. Klasa powinna implementować metodę dodawania, wyszukiwania i usuwania elementu wskazywanego przez klucz.

Zrobiłem to jak zwykłą listę dwukierunkową. Z dodawaniem elementu nie miałem większych problemów, ale jak mam wyszukiwać elementy? Metoda wyszukująca musi umieć porównywać obiekty typu K, które nie są z góry znane (mogą to być inty, stringi albo jakaś moja własna klasa). Co zastosować?

0

<obj1>.Equals(<obj2>)?
EqualityComparer<K>?
Constraint IEquatable<K>? Chociaż w tym wypadku każdy sensowny człowiek powinien również przeciążyć object.Equals i da to ten sam efekt co pierwsze rozwiązanie.

0

Zdecydowanie Equals. Jeśli ktoś w swojej klasie nie zaimplementuje tej metody i porównywanie nie będzie działało tak, jakby chciał, to jego problem.

0

W jaki sposób mam przeciążyć tą metodę? Wywołując object1.Equals(object2); metoda ta zwraca jedynie informację o tym, czy object1 i object2 pokazują na to samo. W moim przypadku oczywiście nie jest to wystarczająca informacja bo aby zaimplementować metodę wyszukującą nie będę sprawdzał czy obiekty pokazują na to samo, ale czy mają takie same wartości w polach klasy K. Konkretnie w klasie z Lista, chciałem napisać coś takiego:

    public Wezel<K, V> wyszukaj(K z)
    {
        Wezel<K, V> pomoc = poczatek;
        while (pomoc.pobierzKlucz() != z)
        {
            pomoc = pomoc.pobierzNastepny();
        }
    }

W jaki sposób należy zatem przeciążyć tę metodę Equals? A może to zadanie da się w ogóle zrobić w inny sposób a ja niepotrzebnie kombinuję?

0

Korzystając z dokumentacji stworzyłem coś takiego:

    public override bool Equals(Object obj)
    {
        Wezel<K,V> WezelObj = obj as Wezel<K,V>;
        if (WezelObj == null)
            return false;
        else
            return key.Equals(WezelObj.key);
    }

    public override int GetHashCode()
    {
        return this.key.GetHashCode();
    }

Na razie działa ok. Zastanawiam się jeszcze dlaczego podczas przeciążania Equalsa koniecznym jest również przeciążenie GetHashCode() ? Tzn. bez tego też działa ale wywala warninga.

1

Nie Ty masz tę metodę przeciążać, tylko twórca klasy, który będzie chciał ją wsadzić do Twojego słownika.
Ty w swoim słowniku masz jej tylko użyć do porównywania obiektów.

0

Chyba nie za bardzo rozumiem...

0

Powyższe przeciążenie mam w klasie Wezel<K,V>. W Slownik<K,V> mam dwa atrybyuty typu Wezel: poczatek i koniec. Metody wyszukujące czy usuwające elementy ze slownika wykorzystują tę przeciążoną metodę Equals dla Wezłów. U mnie dwa węzły są takie same gdy mają taki sam klucz.

0

A zatem, żeby stwierdzić, czy dwa węzły są takie same musisz wywołać obiektWęzła1.Key.Equals(obiektWęzła2.Key), prawda?

0

No właśnie tak.

Ogólnie to kompletnie już tego nie rozumiem.

Jeśli w funkcji głównej zrobię coś takiego:

int x = 5;
int y = 5;
Console.WriteLine(x.Equals(y));

to oczywiście zwróci True.

Jeśli jednak mam jakąś klasę, powiedzmy Osoba, to coś takiego

Osoba a = new Osoba("Adam", "Abacki", 23);
Osoba b = new Osoba("Adam", "Abacki", 23);
Console.WriteLine(a.Equals(b));

zwraca mi False. Jeśli zaś przeciążam Equals to wypisuje true. Przeciążony Equals i cała klasa Osoba wygląda tak:

class Osoba
{
    public string pesel;
    public string imie;
    public int wiek;

    public Osoba(string p, string imie, int wiek)
    {
        this.pesel = p;
        this.imie = imie;
        this.wiek = wiek;
    }

    public override bool Equals(Object obj)
    {
        Osoba OsobaObj = obj as Osoba;
        if (OsobaObj == null)
            return false;
        else
            return pesel.Equals(OsobaObj.p) && imie.Equals(OsobaObj.imie) && wiek.Equals(OsobaObj.wiek);
    }

    public override int GetHashCode()
    {
        return this.pesel.GetHashCode();
    }

Jednak co ciekawe, jeśli użyję tego obiektu (ale zakomentowująć przeciążonego Equalsa w klasie osoba!) w klasie Slownik<K,V> na polu K (klucz), to bez problemu mi usuwa to co chce.

Funkcję usuń w klasie Slownik<K,V> mam zaimplementwaną tak:

    public Wezel<K, V> usun(K ukey)
    {
        Wezel<K, V> pomoc = poczatek;
        while (!(pomoc.pobierzKlucz().Equals(ukey)))
        {
            pomoc = pomoc.pobierzNastepny();
        }

        Wezel<K, V> nastepnyWezel = pomoc.pobierzNastepny();
        Wezel<K, V> poprzedniWezel = pomoc.pobierzPoprzedni();
        poprzedniWezel.ustawNastepny(nastepnyWezel);
        nastepnyWezel.ustawPoprzedni(poprzedniWezel);
        return pomoc;
    }

Oczywiście metoda pobierzKlucz() zwraca obiekt typu K.

1 użytkowników online, w tym zalogowanych: 0, gości: 1