ReferenceEquals

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi !

I come up from a raw C/C++ background and since the pointers in C# are not
so powerfull, i have some diffuculties to understand whats going on behind on
..NET platform. So my question is:
"How can I understand if two references are pointing to the same
adress/object ?"
I found a method "ReferenceEquals", but did not understand , how it works,
cause it behaves a bit strangly and the example of using it on msdn is not
satisfing.
So my example :

object foo = 5;
object cfoo = foo;

bool ok = Object.ReferenceEquals(foo, cfoo);

////////////////////////////////// i get OK
/////////////////////////////////////
if (ok)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");

////////////////////////////////// i get OK
/////////////////////////////////////
if (foo == cfoo)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");

////////why is the value of cfoo 5 if foo and cfoo are pointing to the same
object///
foo = 6;

Console.WriteLine(foo); // 6
Console.WriteLine(cfoo); // 5

////////////////////////////////// now i get not OK
/////////////////////////////////////
if (ok)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");

////////////////////////////////// now i get not OK
/////////////////////////////////////
if (foo == cfoo)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");


so, it seems so both the ==operator and the ReferenceEquals method are just
comparing the values and not if the instances are same.

Am I wrong ? I am highly confused about that and need little help
 
I try to translate to C++:
Hi !

I come up from a raw C/C++ background and since the pointers in C# are not
so powerfull, i have some diffuculties to understand whats going on behind on
.NET platform. So my question is:
"How can I understand if two references are pointing to the same
adress/object ?"
I found a method "ReferenceEquals", but did not understand , how it works,
cause it behaves a bit strangly and the example of using it on msdn is not
satisfing.
So my example :

object foo = 5;
object cfoo = foo;

bool ok = Object.ReferenceEquals(foo, cfoo);


in C++:

void* foo = new int(5);
void* cfoo = foo:

obviously: cfoo == foo
////////////////////////////////// i get OK
/////////////////////////////////////
if (ok)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");

////////////////////////////////// i get OK
/////////////////////////////////////
if (foo == cfoo)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");

////////why is the value of cfoo 5 if foo and cfoo are pointing to the same
object///
foo = 6;

Now you do :

foo = new int(6);

but cfoo still points to the 5 ! Therefore: foo != cfoo
 
thx,

So, do u mean, that i always produce a new Object, if i try to change the
value of an object instance ?
Is it impossible to change the value of an object without creating a new
instance ?
I thought, this happens only by strings.
 
Spongebob said:
Hi !

I come up from a raw C/C++ background and since the pointers in C# are not
so powerfull, i have some diffuculties to understand whats going on behind on
..NET platform.

Well I only know enough C++ to be dangerous, but I'll do what I can...

My first reference (haha) will be this snippet from the docs:
In C#, there are two different kinds of equality: reference equality and
value equality. Value equality is the commonly understood meaning of
equality: it means that two objects contain the same values. For
example, two integers with the value of 2 have value equality. Reference
equality means that there are not two objects to compare. Instead, there
are two object references, both of which refer to the same object.
So my question is:
"How can I understand if two references are pointing to the same
adress/object ?"
I found a method "ReferenceEquals", but did not understand , how it works,
cause it behaves a bit strangly and the example of using it on msdn is not
satisfing.
So my example :

object foo = 5;

This creates an object, 5-in-a-box, which foo references.
object cfoo = foo;

This creates cfoo, which is set to refer to the same 5-in-a-box as foo does.
bool ok = Object.ReferenceEquals(foo, cfoo);

foo and cfoo both refer to the same object, so this is true.
////////////////////////////////// i get OK
/////////////////////////////////////
if (foo == cfoo)

Unless overridden, the == operator checks for *reference equality*, so
this is the same test as the first one.
////////why is the value of cfoo 5 if foo and cfoo are pointing to the same
object///
foo = 6;

This creates a new object, a 6-in-a-box, and sets foo to refer to it.
cfoo continues to refer to the same 5-in-a-box that it did before.
Console.WriteLine(foo); // 6
Console.WriteLine(cfoo); // 5


////////////////////////////////// now i get not OK

Well, not until you change the value of ok, but interpolating

ok = Object.ReferenceEquals(foo, cfoo);

Now since foo and cfoo are referring to different objects, this will be
false.
/////////////////////////////////////
if (ok)
Console.WriteLine("OK");
else
Console.WriteLine("not OK");

////////////////////////////////// now i get not OK
/////////////////////////////////////
if (foo == cfoo)

And as before this is the same test.
Console.WriteLine("OK");
else
Console.WriteLine("not OK");


so, it seems so both the ==operator and the ReferenceEquals method are just
comparing the values and not if the instances are same.

Other way round, but yes you have established that (unless overridden)
operator == checks for reference equality.
Am I wrong ? I am highly confused about that and need little help

You might find Jon Skeet's faq on equality
<http://www.skeet.org.uk/csharp/faq/#equals> useful, and almost
certainly will find at least one useful thing somewhere on his C# pages.
 
Anil said:
thx,

So, do u mean, that i always produce a new Object, if i try to change
the value of an object instance ?
Is it impossible to change the value of an object without creating a
new instance ?
I thought, this happens only by strings.

No. The reason for the confusion is that you're using a "value type" - int.

In .NET, value types, which could also be called "inline types" are
allocated directly within the context in which they are declared, so a local
int variable will have it's value representation stored on the stack, and an
int member variable will have it's value representation stored inline in the
object that it's a member of.

Reference types, on the other hand, are always allocated on the managed
heap. When you write object obj = 5 the value type 5 has to be allocated on
the managed heap, thus "boxing" the literal 5. Your object reference is
then set to point to this boxed integer. There's no simple way change the
value of that boxed integer. Assigning to the reference, e.g. when you
changed it to 6, just boxes up a new integer and updates the reference to
point to that instance.

The same effect will be seen with System::String, which while it's a
reference type, it's instances are immutable, so when you write

object o1 = "test";
object o2 = o1'

....

o1 = "hello";

at this point, o1 and o2 no longer refer to the same object, because
converting a string literal to an object reference is equivalent to

o1 = new String("hello");

not

o1.Value = "Hello";

....Assuming that System.String had a writable Value property, which it
doesn't.

If you used just about any reference class other than System.String, you'd
see your object references behaving exactly like you'd expect from the C/C++
pointer analogy.

-cd
 
Back
Top