چرا در سی شارپ هنگامی که متد Equals را override میکنیم باید متد GetHashCode را نیز اورراید کنیم؟
در برنامهنویسی شی گرا، روشهای Equals و GetHashCode به طور گستردهای برای مقایسه اشیا و استفاده از آنها در ساختارهای دادهای مانند Dictionary و HashSet مورد استفاده قرار میگیرند. هنگامی که شما متد Equals را override میکنید، شما در واقع یک منطق خاص برای مقایسه اشیا خصوصی را ایجاد کردهاید. به همین دلیل باید متد GetHashCode را بازنویسی کنید تا مطمئن شوید که این منطق در کد شما به درستی منعکس شود.
اهمیت override کردن GetHashCode:
- قوانین همسانی: اگر دو شی در منطق
Equalsبرابر شناخته شوند،GetHashCodeنیز باید همین مقدار مساوی را برای هر دو شی برگرداند. این به این معناست که اگر شما دو شی با ویژگیهای یکسان داشته باشید، باید یک کد Hash یکسان نیز برگردانند تا در ساختارهای دادهای درست کار کنند. - عملکرد: هنگامی که اشیا در یک
HashSetیا یک دیکشنری دریافت میشوند، کلیدها بر اساس کد Hash آنها گروهبندی میشوند. اگر دو شی دارای کد Hash متفاوت باشند، هرگز مورد مقایسه قرار نخواهند گرفت، و این ممکن است منجر به از دست رفتن اشیا در ساختار دادهای شود. - ثبات: مهم است که کد Hash در طول عمر یک شی تغییری نکند. بنابراین، فیلدهایی که برای محاسبه این کد استفاده میشوند باید نامتغیر (immutable) باشند. به عنوان مثال، یک ایده خوب این است که از یک فیلد ثابت مانند ID شی برای ایجاد کد استفاده کنید، زیرا تغییر ID به معنای ایجاد یک شی جدید است.
روش پیادهسازی GetHashCode:
در مورد کد Hash ، استفاده از شناسه (برای مثال FooId) به عنوان کد هاش مناسب است. در واقع، فرمول زیر برای پیادهسازی عملکرد GetHashCode بسیار مناسب است:
public override int GetHashCode()
{
return this.FooId.GetHashCode();
}
اگر چندین فیلد دارید که باید در محاسبه کد لحاظ شوند، میتوانید از ترکیبی از آنها استفاده کنید. مثلاً میتوانید از روش زیر برای ترکیب چندین مقدار استفاده کنید:
unchecked
{
int hash = 13;
hash = (hash * 7) + field1.GetHashCode();
hash = (hash * 7) + field2.GetHashCode();
return hash;
}
یا روش دیگر برای دات نت 4.7 به بعد استفاده از Tuple است که امکان ترکیب چند پراپرتی را با هم به شما می دهد:
public override int GetHashCode() => (FooId, FooName).GetHashCode();