1

I've made a simple test :

 object t = 3; object aa = 3; #1 Console.WriteLine(t.Equals(aa)); #2 Console.WriteLine(t.Equals(3)); #3 Console.WriteLine(3.Equals(aa)); 

All of them are true.(that's my problem actually).

looking at object , this is the used function:

 public virtual bool Equals(object obj); 

The equals is virtual. so it can be overridden.

But I don't see any polymorphic behavior. this is just a pure boxed value.

  • Regarding line #1 t.Equals(aa)

    The reference type is the static type - Object.

    so I thought it should call Object.Equals : which means that the reference are different , meaning the first answer should be False.(and I probably wrong here). why is that?

  • Regarding line #2 t.Equals(3)

    Again, t's static type is object. so Object.Equals is running. how come it is true ?

  • Regarding line #3 3.Equals(aa)

    I believe it is the public override bool Equals(object obj); is running because the static type is int. and the param type is object. but why does it true ? does it un-box the value ?

it seems that something , somehow unboxes the object without my notice :-(

0

3 Answers 3

8

Objects Equals method is polymorphic, so it can be overriden by subtypes like int. Int32.Equals overrides this method to do a value comparison between the current object and its argument, and since the arguments are equal once unboxed, it returns true.

There are two overload of Int32.Equals - bool Equals(object) and bool Equals(int). The bool Equals(object) overload is the one overriden from object. Since t and aa are object references, this is the method which will be called in examples 1 and 2.

In example 3, it is still this overload which is called since aa is an object and this is therefore the only valid overload.

The == operator is static and is resolved statically based on the types of its arguments, which are both object in your example. The == operator for object compares references, and in this case will return false for two separate boxed ints.

Sign up to request clarification or add additional context in comments.

13 Comments

in the first line ...which override is occurring ? this one public override bool Equals(object obj); but how ref can be equal to another ref ( I dont care they both hold 3)
@RoyiNamir - They will all call Int32.Equals, however this method does not check for reference equality, it will check the type of its argument is an int, unbox it and then compare its value to the current object (also a boxed int).
@RoyiNamir - There are two what? In the first two examples, the Equals method is called on t, and in the third it's the literal 3.
In int there are 2 Equals. public bool Equals(int obj);public override bool Equals(object obj);`
@RoyiNamir The second one is what is being used to compare the values.
|
5

The virtual method Object.Equals is being called, but because of the way virtual methods work, it calls the Int32.Equals method instead, which compares the int values, not the references.

Virtual methods are bound at runtime. That is, they choose the appropriate method at runtime, not at compile time. In this case, Object.Equals is what is in the compiled code, but since you're comparing ints, it chooses Int32.Equals at runtime. This is accomplished using something called v-tables (in case you wanted to read more on this).

Keep in mind that Equals is supposed to act like this, and if you really want reference equality, you can use ReferenceEquals.

Note that this doesn't have anything to do with boxing. You'll get the same behaviour with, for example, a string, or a custom class.

13 Comments

But I didnt see any Object t = new Int32() here ( polymorphic) it's just a pure box value.....mmmm?
What's the difference between new Int32() and 0? A: None
this line object t = 3; is not boxing ? sure it is
Yes, it is boxing. But the fact that it is boxing is irrelevent to the answer.
3 is the Int32 value 3, much like 0, but 3. What's your question?
|
0

As you wrote in your question the following Asserts will all pass

[Test] public void EqualityOnInts() { object a = 1; object b = 1; Assert.AreEqual(a, b); Assert.IsTrue(1.Equals(a)); Assert.IsTrue(b.Equals(1)); } 

If you instantiate a you create a new integer object with value 1. Calling the Equals method on a will result in calling the Equals method on Int32. Also, if you do a.GetType() it will returnInt32`.

Since the Equals implementation of Int32 will check if the value is equal, and does not care about a different object reference, the result will be "true".

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.