Override Equals и GetHashCode


0

Защо, когато пиша override на Equals VS ми подчертава в зелено класът с текст 
" X overrides Object.Equals(object o) but does not override Object.GetHashCode()"? 
Каква е тази мания на VS да иска от мен да override всичко ? За моята логика HashCode няма никакво значения за това сравнение (ако имаше нямаше да override Equals) :D 
Също да пшитам и това:
Винаги ли се цели да се връщат копия на обектите, за да се запазят оригиналите?
Имам най-обикновена система с 5-6 класа, а всички имат Equals и всяко връща копие на нещата, които се искат (в моя случай копие на List-тове пълни с копия на обекти). Толкова ли "подозрителни" трябва да бъдем към всички потребители на нашите класове? :D




Отговори



1

1. Ето ти подробно и ясно, защо и как -> лекцията е "Equality and Comparison" [DL Link]

2. Ето защо, GetHashCode() не е същото като Equals метода и разликата с адреса на паметта [LINK]

Лекцията е много препоръчителна. Лекционният материал се взема за 3h при 1.7 скорост, в което време е включено работа с кода към лекцията и тестове.(слайдовете и кода са в rar)

Статията е страхотна. Аз в момента с кеф си я препрочитам.

С две ръце ти препоръчвам да гледаш материала "Equality and Comparison". Така ще разбереш, защо, как и какво се случва. 

3. Също така виж разликата м/у Class и Struct (reference type vs value type) [ТУК] + Как да прецениш кога да използваш кое [ТУК]

Директен отговор на въпроса ти:
Понеже не си дал ясен пример, какво точно създаваш, няма как да ти се обясни ясно, пълно и коректно - така че да бъде разбрано. Т.е. дай конкретни примери, над които работиш.

P.S. Ако override-неш object.Equals() за типа си, добра практика е да overflow-неш операторите == и !=. Иначе става като Tuple например: Tuple aValue.Equals(Tuple aValue`) -->True, но Tuple aValue == Tuple aValue` --> False (защото == няма овърфлоу, конкретно, и прави default-ното референтно сравнение за равенстно, вместо по стойности) и т.н. Как точно да го направиш, мога да ти обясня, но по-добре гледай видео материала.


от V.Profirov (1122 точки)


0

edit: Но явно го правя грешно като цяло. Май трябва просто да връщам обектите и ако потребителя ги омаже те са си негови в крайна сметка ... 
Принуждавам класа да се държи като структура, пиша много повече код, хабя повече рам само да предвидя, че потребителя може да омаже и дори ограничавам неговите функции вероятно (ако той вземе 1 лист и му приложи негови си методи то няма да се отрази на оригинала). 
Явно си губя времето с това - ще изгледам материалите, за да знам как се прави, но няма да усложнявам домашното с глупости. 

edit(2): За това домашно става въпрос: Линк. И по-специално за 1-ва задача. Пъвоначално си мислех да връщам винаги копие, но ако връщам копия то реално, този който ползва системата няма да има достъп до оригиналите. Примерно мога да връщам копие на листа, но със същите обекти. Ако потребителя иска да прави нещо по някой обект да си го променя(примерно да промени броя лекции в определена дисциплина), а самите листове имат Add и Remove отделни методи, с валидации и ако иска да ги промени трябва да ги използва. 
Да не говорим, че гледах домашни от минали години - хората чисто си връщат оригиналите и не им дреме да енкапсулация. 
Честно нямам представа как е по-правилно да се направи. Това с копие на всичко направо отива към структура, а не мисля че това е целта за това задание. 


от StoikoNeykov (2621 точки)

1

Доколкото виждам имаш ентусиазма да работиш по текущите задачи/проблеми, но са ти малко омотани нещата, което е нормално.

Предлагам ти да си направиш flowchart или brain map, на конкретна задача по която работиш.
Срещу всеки сегмент да напишеш като въпроси какво не се получава и какво не е ясно.
След това да дадеш термин и граници на всеки въпрос, например енкапсулацията не ми се получава - какво ще е енкапсулация за моя случей и какво е по принцип.
Ограничи си, кои са ти 2-3те неща, които ако си разясниш най-много ще придвижат твоето решение към сполучлив край.
Отдели около 5 мин да прегледаш по диагоналната система най-популярните места със ситематизиран отговор и тези с практичен. Ограничи се до 3-4. Пример: blackwasp и/или msdn - за wiki тип отговор, codeproject - wiki/практичен (50%|50%), и StackOverflow - за практичен (чети не само маркираният за най-добре отговорен).

Задай си време от по около 20-25 мин за всеки, в 3-4 стъпки (Разцепване на : термин, връзка(отношение със средата), функционалност, тест). Не прескачай времето! Стреми се с 20% от прочетеното да постигнеш 80% от разбирането, над което да приложиш най-голямо количество тестове (твои тестове) за това време.

След това, изчисти си въпросите които са останали и са ти неясни все още. Ще познаеш, кои са, ако сам не можеш да им дадеш "отговор в огледало". Тях може/трябва да зададеш на лекторите при следващата лекция, или във форума - в този ред.
Търси от лекторите насоки за връзки с материала и конкретно обяснение - подплатено както с премер, така и с кратка форма на теорията, включващо "under the hood" (настoявай и за 2те). От форума: гледай да си възможно най, най-конкретен.
P.S. Успех и горе главата :) Ако продължаваш да се затрудняваш не спирай да питаш, но спазвай правилото "You cannot solve a problem with the same mind that created it."

P.S. Относно "потребителите", на твоя код, може да следваш градивната схема:
1-во пишеш все едно, че ти си потребителят
2-ро все едно, че е TheГеймър ("знам, знам, аз съм най-добрия, ама това е бъгнато")
3-то все едно, че е баба ти
4-то все едно, че е маймунка и блъска по клавиатурата и ще се радва, ако излезе накрая нещо готино на екрана
5-то, ако си удовлетворил всичко по-горе (1-4), значи може да имаш увереността да се опиташ да го направиш все едно, че Senior Dev. ще го преглежда
6-то и последно, прецени си, кое ниво ще задоволи директно ситуацията (кой конкретно ще го ползва (1-4)) и дали имаш време да направиш 5-та точка. След няколко цикъла, схващайки подхода направи 6-то да е 0-ево. Не спирай да се стремиш към 5-то, но следи отделеното време.


от V.Profirov (1122 точки)



1

По правило 2 обекта се считат еднакви, ако хешкодовете им са еднакви.

Пост в SO, който също до някъде отговаря на въпроса ти.

Ако искаш да се сравняват според правила създадени от теб, няма проблеми, ще се компилира, но ще си светка VS-a. Можеш да suppress-неш warning-a в настройките.


от Pip3r4o (3392 точки)


0
Т.е. трябва да напиша е как да разбера за кое да върна същия хешкод? 
Потребителя пита за 2 различни (дори случайни) обекта как да разбера за кои точно да върна същия хешкод? Няма как да сравнявам всички инстанции на този клас и евентуално ако има някъде копия да върна същия. 
Варианта, който ми хрумва е да "измисля" случайно число (примерно направи името на обекта на int-ове събери ги, направи същото за всяко друго поле на обекта и накрая изпиши "случайно" число). Т.е. така получените обекти ще имат еднакъв хешкод, но може различни обекти да върнат еднакъв зависимост от полетата. 
Хммм попрочетох и точно това си пише ... т.е. да си измисля :D 

от StoikoNeykov (2621 точки)


1

Здравей,

Постът в SO отговаря по-правилно на въпросът ти. Понеже еднаквите хешове не са гаранция за еднаквост VS те кара да имплементираш GetHashCode сам по такъв начин, че да си гарантираш, че еднаквите обекти връщат еднакъв хеш винаги.

По втория въпрос - да, трябва да си подозрителен към всички :) Trust no one. :) В описания сценарии мисля, че ще е достатъчно да връщаш копие на списъка от обекти, а не чак копие от списък с копия на обекти вътре.

Поздрави.


от nikolavn (319 точки)


-1
Работата е, че до сега си мислех, че хешкода връща адреса от паметта, където стои променливата. (т.е. самата референция в някакъв формат, който може да се използва на ниско ниво) 
Така измислен хешкода, който не гарантира еднаквост ... за какво му е на някой това ? :D 
Пример: моя метод GetHashCode() връща на котката годините + 58 (защото защо не), ако не е котка викам от base (не зная причина да не викам винаги от base, но както и да е) И еднаквите котки връщат еднакво - перфектно ! И как някой ще използва това число (ако се напрвят 1000 инстанции на този клас ще има много еднакви). 
Явно пропускам цялата идея :D 
edit: Попрочетох и явно има някакво значение. Единственото, което се сещам е просто да го пазя в променлива и да се изчислява от DateTime.Now по някакъв начин, просто да не се вижда полето, но да има GetHashCode(), и все пак ми е странно :D 

от StoikoNeykov (2621 точки)