471,334 Members | 1,434 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,334 software developers and data experts.

Explanation of object equality.

In the interests of me saving hair, can someone please explain to me
what's going on below? Why doesn't == work in comparing two int's when
cast as objects? They're the same type.

Note that it worked for strings.

Thanks in advance,
Damien
---------------
using System;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
test();
}

static public void test()
{
object o1 = 5;
object o2 = 5;
Console.WriteLine(o1==o2); // returns false - why is this?
Console.WriteLine(o1.Equals(o2)); // returns true

// Check they're the same type
Console.WriteLine(o1.GetType().FullName); // Returns
System.Int32
Console.WriteLine(o2.GetType().FullName); // Returns
System.Int32

// try specifically casting
Console.WriteLine(Convert.ToInt32(o1) ==
Convert.ToInt32(o2)); // returns true

// How about with strings?
object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true
Console.WriteLine(o3.Equals(o4)); // returns true

Console.ReadLine();
}
}
}
Sep 12 '08 #1
16 1528
On Thu, 11 Sep 2008 21:24:24 -0700, DamienS <da**********@yahoo.com.au>
wrote:
In the interests of me saving hair, can someone please explain to me
what's going on below? Why doesn't == work in comparing two int's when
cast as objects? They're the same type.
But the Object class's == operator doesn't call Object.Equals(). It's
just a straight reference equality test. Since each variables refers to a
different instance, the references aren't equal and so the test fails.
Note that it worked for strings.
Because the String class == operator overload does essentially call the
Equals() method.

Pete
Sep 12 '08 #2
Damien... Be careful. As Jon has pointed out in the past, the
overloaded
string equality operator only works on reference variables of Type
string.

object a= "Hello";
object b= "Hello";
bool isSameReference= (a == b); // test if a and b contain references to
the
same object or to no object (are both null)
bool isSameContent= ((string)a == (string)b); // test if string
referenced by a
and string referenced b have the same content/value or a and b are both
null

Session["KEY"]="VALUE"; // Error! The left hand operand is of type
object!
This is a reference based comparison. Do this:
(String)Session["KEY"]="VALUE"; // content equivalence

Regards,
Jeff
>>// How about with strings?
object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true<<
*** Sent via Developersdex http://www.developersdex.com ***
Sep 12 '08 #3
On Thu, 11 Sep 2008 22:08:22 -0700, Jeff Louie <an*******@devdex.com>
wrote:
Damien... Be careful. As Jon has pointed out in the past, the
overloaded
string equality operator only works on reference variables of Type
string.
Note that this is true for any overloaded operators. That is, the
operator is chosen according to the static (compile-time) type of the
operand(s). The warning to be careful is a good one, and worth keeping in
mind when using _any_ overloaded operators.

Pete
Sep 12 '08 #4
"DamienS" <da**********@yahoo.com.auwrote in message
news:72**********************************@z11g2000 prl.googlegroups.com...
Note that it worked for strings.

// How about with strings?
object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true
Console.WriteLine(o3.Equals(o4)); // returns true
Even though it worked for strings in your example, note that it may not
always work in the way you expect.

e.g. :
==
object o3 = "hello";
object o4 = "hello";
object o5 = "hello".ToLower();

Console.WriteLine(o3 == o4); // true
Console.WriteLine(Object.ReferenceEquals(o3, o4)); // true
Console.WriteLine(String.Equals(o3, o4)); // true

Console.WriteLine(o3 == o5); // false !!!!
Console.WriteLine(Object.ReferenceEquals(o3, o5)); // false
Console.WriteLine(String.Equals(o3, o5)); // true
==

Note the result of (o3 == o5) is false, because the references of the two
strings are different. It happens to return true in the (o3 == o4) test
because the two references happens to be the same.
Sep 12 '08 #5

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
>
>Note that it worked for strings.

Because the String class == operator overload does essentially call the
Equals() method.
Peter,

Note that in the example shown by the op :

object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

that the String class == operator is *not* being called.
It just happens to return true because the references to o3 and o4 are the
same.



Sep 12 '08 #6
"Moe Sisko" <nullwrote in message
news:ed**************@TK2MSFTNGP02.phx.gbl...
>
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
>>
>>Note that it worked for strings.

Because the String class == operator overload does essentially call the
Equals() method.

Peter,

Note that in the example shown by the op :

object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

that the String class == operator is *not* being called.
It just happens to return true because the references to o3 and o4 are the
same.
It is true that the references are the same since the compilier creates only
one "hello" string. However the strings == overload will surely be called
what other choice is there? Its quite likely that the overload will do a
reference equality comparison first.

--
Anthony Jones - MVP ASP/ASP.NET

Sep 12 '08 #7
"Anthony Jones" <An***********@yadayadayada.comwrote in message
news:Os**************@TK2MSFTNGP04.phx.gbl...
"Moe Sisko" <nullwrote in message
news:ed**************@TK2MSFTNGP02.phx.gbl...
>>
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
>>>
Note that it worked for strings.

Because the String class == operator overload does essentially call the
Equals() method.

Peter,

Note that in the example shown by the op :

object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

that the String class == operator is *not* being called.
It just happens to return true because the references to o3 and o4 are
the same.

It is true that the references are the same since the compilier creates
only one "hello" string. However the strings == overload will surely be
called what other choice is there? Its quite likely that the overload
will do a reference equality comparison first.
Oops stratch that! The variable types are object. There is no way the
string == overload will ever be called. Its too early in morning :(

--
Anthony Jones - MVP ASP/ASP.NET

Sep 12 '08 #8
However the strings == overload will surely be
called what other choice is there?
The alternative is a referential equality check; since the operands are
"object", and operator overloads are determined by static analysis -
this is what happens. To demonstrate:

object o3 = "hello";
string s = "hel";
if (o3 != null) s += "lo";
object o4 = s;
// now o3 and o4 contain "hello"
Console.WriteLine(o3 == o4); // returns false

For info, this is implemented as a direct reference test:

ldloc.0 // o3
ldloc.2 // o4
ceq // ==

Marc
Sep 12 '08 #9

"Marc Gravell" <ma**********@gmail.comwrote in message
news:e9**************@TK2MSFTNGP04.phx.gbl...
>However the strings == overload will surely be
called what other choice is there?

The alternative is a referential equality check; since the operands are
"object", and operator overloads are determined by static analysis - this
is what happens. To demonstrate:

object o3 = "hello";
string s = "hel";
if (o3 != null) s += "lo";
object o4 = s;
// now o3 and o4 contain "hello"
Console.WriteLine(o3 == o4); // returns false

For info, this is implemented as a direct reference test:

ldloc.0 // o3
ldloc.2 // o4
ceq // ==
Yes, sorry Marc for wasting your time, I was half asleep.

--
Anthony Jones - MVP ASP/ASP.NET

Sep 12 '08 #10
On Thu, 11 Sep 2008 23:17:23 -0700, Moe Sisko <nullwrote:
Peter,
Moe,
Note that in the example shown by the op :

object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

that the String class == operator is *not* being called.
I never said it was. In fact, the whole point of my post was to point out
that it's not.

I don't disagree with what you wrote, but I don't understand why you are
replying to my post simply to reiterate what I wrote.

Pete
Sep 12 '08 #11

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
I never said it was. In fact, the whole point of my post was to point out
that it's not.

I don't disagree with what you wrote, but I don't understand why you are
replying to my post simply to reiterate what I wrote.

Pete
Pete,

It's just the way I interpreted your post, in the context of the op's
original post.

The op's original post said :
==
Note that it worked for strings.
....
.... ** then later down, this is his supporting evidence for "it worked for
strings" **

// How about with strings? ** Code Snippet X **
object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true
Console.WriteLine(o3.Equals(o4)); // returns true
==
To which you replied :
==
Note that it worked for strings.
Because the String class == operator overload does essentially call the
Equals() method.
==

Your explanation for "why it worked for strings", sounds like its saying
that "code snippet X" is causing the string class == operator overload to be
invoked. Or at least that's how I (wrongly) interpreted your post.

Sorry if there was any misunderstanding.

Moe.



Sep 12 '08 #12
Peter Duniho wrote:
>Note that in the example shown by the op :

object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

that the String class == operator is *not* being called.

I never said it was.
Yes, you did.

You said:

"Because the String class == operator overload does essentially call the
Equals() method."

The reason that the object references are compared is _not_ that the
string class == operator calls the Equals method. The reason that the
object references are compared is because the two variables that are
compared are two object references. It's the object class == operator
that is being called, not the string class == operator.

--
Göran Andersson
_____
http://www.guffa.com
Sep 13 '08 #13
Damien... Did we answer your question? You asked:

// How about with strings?
object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

Strings are a very special case. First, when both operands are of type
String,
the overloaded equality operator checks for content equivalence. In your
example however, the operands are of type object, not String, so the
object
equality operator is called, not the overloaded string equality
operator. The
object equality operator checks to see if o3 and o4 both contain
references to
the same object or are both null.

Second, unlike most objects, string storage is more fully optimized.
Strings
are shared or interned so that the o3 and o4 variables both contain
references to a single interned string.

"The common language runtime conserves string storage by maintaining a
table, called the intern pool, that contains a single reference to each
unique
literal string declared or created programmatically in your program.
Consequently, an instance of a literal string with a particular value
only exists
once in the system."

http://msdn.microsoft.com/en-us/libr...ng.intern.aspx

Due this optimization or interning, the o3 and o4 variables contain
references
to the same string object and the call returns true.

At this risk of telling you "more than you really wanted to know", most
objects, not just strings, _are_ optimized to some extent. Each instance
of a
class may contain methods and fields, but the compiler is able to
optimize
the code in memory, so that instance methods, but not fields, are shared
to
reduce memory requirements.

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Sep 13 '08 #14
On Sat, 13 Sep 2008 03:26:58 -0700, Göran Andersson <gu***@guffa.com>
wrote:
Peter Duniho wrote:
>>Note that in the example shown by the op :

object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

that the String class == operator is *not* being called.
I never said it was.

Yes, you did.
No, I didn't. Not in the context of the quoted text here.
You said:

"Because the String class == operator overload does essentially call the
Equals() method."
The statement to which I was responding was discussing the _Object_ class
overload, not the String class overload. You even quoted the text that
shows that.

You should read more carefully.
The reason that the object references are compared is _not_ that the
string class == operator calls the Equals method.
I never said it was. In the context of variables typed as Object, the
String class == operator is irrelevant and I already said as much. The
only place I mentioned the String class == operator was in the context of
variables typed as String.
The reason that the object references are compared is because the two
variables that are compared are two object references. It's the object
class == operator that is being called, not the string class == operator.
I know. That's what I wrote.

Pete
Sep 13 '08 #15
G'day everyone and thanks for all your posts. My apologies for the
delayed reply.
Damien... Did we answer your question? You asked:
Look, to tell you the truth, I was thouroughly confused until your
explanation Jeff of interned strings. I've never heard of them. It's
far from it being "more than I wanted to know" - in fact, I guess
that's exactly the answer I was looking for when I posted the
question; namely an explanation of what I saw was an apparent
inconsistency. So - thanks for that :-)

For what it's worth, I do think that there's a language inconsitency
in that, for the following, Result=true:
object o1 = "hello";
object o2 = "hello";
bool Result = o1.Equals(o2);

Whilst Interning explains it perfectly, I don't necessary agree with
the design of the language in permitting it, as it introduces
inconsistent behaviour. Surely the "interning engine" in the compiler
could determine that the objects were allocated differently and were
possibly intended by the devloper to indeed 'be' different, whilst
still maintaining the memory efficiency behind the scenes. I think
that the current set up is a prone to bugs ('twas a bug which spawned
this thread in the first place). Anyway - my opinions are neither here
nor there and largely inconsequential. In any case, it's definitely a
trap for young players :-)

Thanks very much to all who posted. I especially enjoyed the "You
said... No I didn't... yes you did..." argument :-)

Damien.
>
// How about with strings?
object o3 = "hello";
object o4 = "hello";
Console.WriteLine(o3 == o4); // returns true

Strings are a very special case. First, when both operands are of type
String,
the overloaded equality operator checks for content equivalence. In your
example however, the operands are of type object, not String, so the
object
equality operator is called, not the overloaded string equality
operator. The
object equality operator checks to see if o3 and o4 both contain
references to
the same object or are both null.

Second, unlike most objects, string storage is more fully optimized.
Strings
are shared or interned so that the o3 and o4 variables both contain
references to a single interned string.

"The common language runtime conserves string storage by maintaining a
table, called the intern pool, that contains a single reference to each
unique
literal string declared or created programmatically in your program.
Consequently, an instance of a literal string with a particular value
only exists
once in the system."

http://msdn.microsoft.com/en-us/libr...ng.intern.aspx

Due this optimization or interning, the o3 and o4 variables contain
references
to the same string object and the call returns true.

At this risk of telling you "more than you really wanted to know", most
objects, not just strings, _are_ optimized to some extent. Each instance
of a
class may contain methods and fields, but the compiler is able to
optimize
the code in memory, so that instance methods, but not fields, are shared
to
reduce memory requirements.

Regards,
Jeff

*** Sent via Developersdexhttp://www.developersdex.com***
Sep 16 '08 #16
On Sep 16, 6:59*am, DamienS <damiensaw...@yahoo.com.auwrote:
G'day everyone and thanks for all your posts. My apologies for the
delayed reply.
Damien... Did we answer your question? You asked:

Look, to tell you the truth, I was thouroughly confused until your
explanation Jeff of interned strings. I've never heard of them. It's
far from it being "more than I wanted to know" - in fact, I guess
that's exactly the answer I was looking for when I posted the
question; namely an explanation of what I saw was an apparent
inconsistency. So - thanks for that :-)

For what it's worth, I do think that there's a language inconsitency
in that, for the following, Result=true:
object o1 = "hello";
object o2 = "hello";
bool Result = o1.Equals(o2);

Whilst Interning explains it perfectly
No, interning isn't really relevant in the above. The above will call
the *overridden* method in string.

Interning is only relevant when you're using ==, where the compiler
just uses the normal object definition, i.e. reference equality. This
is the big difference between overriding and overloading - overriding
is an execution time decision based on the actual type of the object.
Overloading is a compile time decision based on the declared types of
the arguments/operands.
I don't necessary agree with
the design of the language in permitting it, as it introduces
inconsistent behaviour. Surely the "interning engine" in the compiler
could determine that the objects were allocated differently and were
possibly intended by the devloper to indeed 'be' different, whilst
still maintaining the memory efficiency behind the scenes.
How could it determine that the objects were allocated "differently"?
They're allocated in the same way in two different lines, that's all.

I don't see any problem with string interning being in the language -
so long as it's well documented (which it is in the C# spec).

Jon
Sep 16 '08 #17

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Bijay Kumar | last post: by
reply views Thread by Bijay Kumar | last post: by
14 posts views Thread by serge calderara | last post: by
20 posts views Thread by nicolas.pourcelot | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.