2

As far as I know Class and Object are reference type.

I have below method to Change the Value

public void ChangeValue(MyClass classobj)
{
    classobj.Number = classobj.Number*2;
}

I invoke the method to double the value

var myClass=new MyClass();
int myNumber = 10;
myClass.Number = myNumber;
ChangeValue(myClass);

And it will be return 20 which is fine as you can interpret it as when you make object of your class then it pass reference to method and it will update the reference values.

but my question is why its not happening for Object type. In other words why when I make object and assign some value to it like below

 object myObject = new object();
 string sometext  = "Some object value";
 myObject = sometext;
 ChangeValue(myObject)

it wont change the value after executing the method

public void ChangeValue(object objectValue)
{
    objectValue = null;
}

I know the parameter of methods are value types but can not understand it have different behavior for two reference type.

RB.
  • 36,301
  • 12
  • 91
  • 131
wikinevis
  • 189
  • 1
  • 2
  • 11
  • 1
    Have a read of this: http://www.yoda.arachsys.com/csharp/parameters.html A great explaination on method parameter passing. – Jason Evans Feb 22 '13 at 11:37
  • Just rememboer: `object` is an alias `System.Object` which is a class and that means it is a reference types. – Soner Gönül Feb 22 '13 at 11:37
  • 1
    Also: http://stackoverflow.com/questions/3272861/reference-and-value-types-scenario http://stackoverflow.com/questions/1658985/what-is-a-value-class-and-what-is-a-reference-class-in-c – Jason Evans Feb 22 '13 at 11:37

3 Answers3

2

You're actually doing two different things here. Object and your MyClass are indeed both reference types, which means you pass a reference to the actual object into the ChangeValue method. However, the reference that you see inside the method is a copy of the reference the caller holds. They point to the same object, so when you manipulate the object in the method the caller of the method can see your changes, but changes to the actual reference inside the method only affect the method itself.

In an attempt to summarise, objects are passed by reference, but those references are passed by value.

In your method

public void ChangeValue(object objectValue)
{
    objectValue = null;
}

What you're actually doing is reassigning the reference objectValue, and that reference is a copy of the reference called myObject which the caller has. Because the method only has a copy, it can't affect the caller's reference at all.

There is a way to make this work, you have to pass the reference by reference. Which always gives me a headache, but that's what the ref keyword is for.

public void ChangeValue(ref object objectValue)
{
    objectValue = null; // this is the SAME reference as the caller has, so the caller will see this change
}

However then it also has to be called that way:

ChangeValue(ref myObject);

so that it's obvious at the call site that it might come back pointing to a different object. It's important to know that, as you might still have things relying on the old value and end up in a horrible confused mess if references were pointing to different objects unexpectedly.

Matthew Walton
  • 9,809
  • 3
  • 27
  • 36
  • I can see what you mean which is indeed right. My question come along with your interpret which is "Why the value of myClass is change in the ChangeValue(MyClass classobj) ?" Imagine the copy of the myclass reference coming to the method and I change the classobj.Number = 0; then how it will notify the caller about this change ? – wikinevis Feb 22 '13 at 11:57
  • It's not a matter of telling the caller about the change. The caller and the method both see and modify the same object because they both have a reference to it. If the caller looks at the object after the method has run it will see the changes because the method has changed the same object. – Matthew Walton Feb 22 '13 at 15:31
1

You pass the objectValue to the ChangeValue(object objectValue) by value and this value is a reference. Then you change this value, but not the value of the myObject.

You have to pass it as ChangeValue(ref object objectValue) to actually pass the value of reference by reference.

aush
  • 2,108
  • 1
  • 14
  • 24
  • I did the same thing to myclass object , I make object of it then pass it to Changevalue(MyClass objClass)and this value is a reference type. Then i change the value of it to 20 and it reflect my caller object value as well. Then why it was work for myClass object ? – wikinevis Feb 22 '13 at 11:49
  • @wikinevis, Because you haven't changed the value of the myClass actually (value of the myClass is a reference), you have changed the value of the object which is referenced by the myClass. – aush Feb 22 '13 at 11:57
0

It's not a different behavior, you're doing different things

This will work exactly as your object example:

    public void ChangeValue(MyClass classobj)
    {
        classobj = null;
    }

And this will work as your first example(assuming you will pass MyClass instance):

   public void ChangeValue(object objectValue)
    {
        ((MyClass)objectValue).Number *= 2;
    }

What realy happens here is that when you are assigning parameter (not a property or field of parameter) you are only changing that parameter's value. Original value and variable in calling code stay intact.

The same happens here:

MyClass a = new MyClass();
MyClass b = a;
a = null;
// b still contains the value created in the first line

Simply speaking, reference variables hold the pointer (memory address) of the actual value. By changing variable's value, you are making it point to different object or null. But when you are doing a.field=2 this means you are taking the object a is referencing to and changing it's field member value.

Anri
  • 6,175
  • 3
  • 37
  • 61