76. The difference between Equals and == operator

לעתים נפוצות אנחנו רוצים להשוות אובייקטים.

קיימים שתי דרכים פופולאריות לעשות זאת

הדרך היותר פופולארית: להשתמש באופרטור ==:

1
2
3
4
5
6
7
string myFirstString = "Hello";
string mySecondString = "Hello!";
if (myFirstString == mySecondString)
{
// ...
}

הדרך השנייה היא באמצעות המתודה הוירטואלית Equals:

1
2
3
4
if (myFirstString.Equals(mySecondString))
{
// ...
}

האם אי פעם תהיתם מה ההבדל בין המתודות?

ראשית הoperator == היא מתודה סטטית ואילו המתודה Equals היא מתודה וירטואלית של object.

במה מתבטא ההבדל?

שימו לב לקוד הבא:

1
2
3
4
5
6
7
int myFirstNumber = 3;
int mySecondNumber = 3;
if (myFirstNumber == mySecondNumber) // true
{
//
}

ולקוד הבא

1
2
3
4
5
6
7
object myFirstNumber = 3;
object mySecondNumber = 3;
if (myFirstNumber == mySecondNumber) // false
{
//
}

לעומת זאת אם היינו כותב Equals במקום, זה היה עובד. למה?

== זה פונקציה סטטית ולכן היא לא בודקת את הסוג של האובייקטים בזמן ריצה.

לעומת זאת Equals היא פונקציה וירטואלית ומפוענחת בזמן ריצה.

אז למה בדוגמה השנייה זה לא נכנס לif?

האופרטור == מפוענח בזמן קימפול בתור הפונקציה הסטטית הזו:

1
public static bool operator == (object a, object b)

ה== של object משווה Referenceים. מאחר ומתבצע פה boxing, יש פה שני referenceים שונים, ולא מדובר באותו אובייקט.


באופן כללי קיימות שתי הפונקציות.

המטרה של Equals זה לבדוק ששני אובייקטים שווים באיזשהו מובן (למשל, נוכל ליצור מחלקת string משלנו, שבה "Hello" ו"hello" יהיו שווים בEquals)

לעומת זאת, המטרה של == היא לבדוק ששני אובייקטים זהים תמיד (כלומר "אותו הדבר")

לדוגמה:

1
2
3
4
5
6
7
8
9
10
11
12
13
StringBuilder firstBuilder =
new StringBuilder("Hello");
StringBuilder secondBuilder =
new StringBuilder("Hello");
if (firstBuilder.Equals(secondBuilder)) // true
{
}
if (firstBuilder == secondBuilder) // false
{
}

שימו לב שEquals מחזיר true לעומת == שמחזיר false. למה זה הגיוני?

כרגע מבחינת תוכן שני הbuilderים האלה הם שווים.

לעומת זאת, הם לא בהכרח יהיו תמיד זהים, כלומר נוכל לשנות את הbuilder הראשון ואז לא יהיו שווים מבחינת הEquals. לכן הגיוני שהם לא זהים.

שימו לב שזה עניין של סמנטיקה. יכלו גם לדרוס את == ולדאוג שהוא יתנהג כמו Equals.


לבסוף, נסביר למה בעצם קיימות שתי הפונקציות. יש לזה 3 סיבות עיקריות:

  1. הקריאה a.Equals(b) זורקת Exception אם האיבר הראשון הוא null, לעומת הקריאה a == b
  2. הoperator הסטטי היא פונקציה שמפוענחת בזמן קימפול, ולכן עלותה נמוכה יותר
  3. לפעמים היינו רוצים שEquals ו== לא יחזירו אותו ערך

שבוע שווה!

שתף