مقدمه
ما به طور طبیعی از عملگرهایی مانند `+`، `-` یا `==` برای کار با انواع دادهی پایهای مثل int و
double استفاده میکنیم. برای مثال، عبارت 5 + 10 کاملاً قابل فهم است. اما اگر بخواهیم دو شیء
از نوع سفارشی خودمان (مثلاً دو شیء از کلاس Point که نمایندهی یک نقطه در فضا هستند) را با هم
جمع کنیم چه؟ به طور پیشفرض، کامپایلر نمیداند چگونه عملگر `+` را بر روی این اشیاء اعمال کند.
سربارگذاری عملگر (Operator Overloading) ویژگی قدرتمندی در C# است که
به ما اجازه میدهد تا پیادهسازی سفارشی خود را برای عملگرهای استاندارد تعریف کنیم. این کار باعث
میشود که انواع دادهی سفارشی ما رفتاری طبیعیتر و شبیه به انواع دادهی داخلی زبان داشته باشند و
کد ما خواناتر شود.
سربارگذاری عملگرها چیست؟
سربارگذاری عملگر به معنای تعریف یک متد استاتیک ویژه در کلاس یا ساختار است که به کامپایلر میگوید
هنگام مواجهه با یک عملگر خاص بر روی اشیاء آن نوع، چه کاری باید انجام دهد. در واقع، این یک نوع
"شکر نحوی" (syntactic sugar) است که به جای فراخوانی یک متد با نامی مانند Add(p1, p2) به ما
اجازه میدهد تا به سادگی بنویسیم p1 + p2. این کار باعث میشود کدی که با مفاهیم ریاضی یا فیزیکی
(مانند بردارها، ماتریسها یا اعداد مختلط) سروکار دارد، بسیار تمیزتر و شبیهتر به فرمولهای اصلی
شود.
نحوهی سربارگذاری یک عملگر
برای سربارگذاری یک عملگر، باید یک متد public static در کلاس یا ساختار خود تعریف کنید. این متد
از کلمهی کلیدی operator و به دنبال آن، خودِ عملگری که میخواهید
سربارگذاری کنید، استفاده میکند. بیایید یک ساختار Point بسازیم و عملگر `+` را برای آن
سربارگذاری کنیم.
Program.cs
public struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) { X = x; Y = y; }
public static Point operator +(Point p1, Point p2)
{
int newX = p1.X + p2.X;
int newY = p1.Y + p2.Y;
return new Point(newX, newY);
}
public override string ToString() => $"({X}, {Y})";
}
در این کد، ما یک متد استاتیک تعریف کردهایم که دو شیء Point را به عنوان ورودی میگیرد و یک شیء
Point جدید که حاصل جمع مختصات آنهاست، برمیگرداند. اکنون میتوانیم از آن به صورت زیر استفاده
کنیم:
Program.cs
Point point1 = new(1, 2);
Point point2 = new(3, 4);
Point point3 = point1 + point2;
Console.WriteLine(point3);
سربارگذاری عملگرهای مقایسهای
شما میتوانید عملگرهای مقایسهای مانند == و != را نیز سربارگذاری کنید. این کار به شما اجازه
میدهد تا منطق برابری سفارشی خود را تعریف کنید.
قوانین مهم:
- عملگرهای مقایسهای باید به صورت جفت سربارگذاری شوند. اگر == را سربارگذاری میکنید،
باید != را نیز سربارگذاری کنید. همین قانون برای < و > و همچنین <= و
>= نیز صادق است.
- هنگام سربارگذاری == و !=، قویاً توصیه میشود که متدهای Equals و GetHashCode را نیز
بازنویسی (override) کنید تا رفتار نوع شما در تمام سناریوها (مانند استفاده در دیکشنریها)
یکسان و قابل پیشبینی باشد.
Program.cs
public static bool operator ==(Point p1, Point p2)
{
return p1.X == p2.X && p1.Y == p2.Y;
}
public static bool operator !=(Point p1, Point p2)
{
return !(p1 == p2);
}
public override bool Equals(object obj) => obj is Point other && this == other;
public override int GetHashCode() => HashCode.Combine(X, Y);