Confusion when Passing Reference Type Objects in C#
Everybody knows that when making a method call in C#, reference type objects are passed by reference. In other words, whatever changes you make to your object in the called method will be reflected on the original one.
Let's examine the following code:
If you run the preceding code, it will show the following result:
Value before method call: 5
Value after method call: 10
This was expected. However, the idea that all reference type objects are passed by reference is not really accurate and the following proves so. If we change "MyMethod" by adding one line so it becomes as the following:
and then we run the program, guess what the result will be. The result will be as following:
Value before method call: 5
Value after method call: 5
The value of the field "MyInteger" did not change as you might expected. That is because what actually happens when you pass a reference type object to a method is that the reference to that object is copied and the copy is passed to the method. The new copy of the reference points to the same object, so if you make changes in the called method, you will be making changes on the same object. But if you create a newobject in the called method, you will be actually changing the reference value that was passed and making it point to a new object. And whatever changes you make after this step will be irrelevant to the original object.
The following diagrams illustrates what happens in the previous 2 examples.
If you wish to make any changes to the object in the called method and have them all reflected on the original object even if you make a new instance in the called method, then what you need is to pass it by reference. You need to add the keyword
Let's examine the following code:
1
2
3
4
| class MyClass { public int MyInteger; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| class Program { static void Main( string [] args) { MyClass myClass = new MyClass(); myClass.MyInteger = 5; Console.Write( "Value before method call: " ); Console.WriteLine(myClass.MyInteger); MyMethod(myClass); Console.Write( "Value after method call: " ); Console.WriteLine(myClass.MyInteger); } private static void MyMethod(MyClass myClass) { myClass.MyInteger = 10; } } |
Value before method call: 5
Value after method call: 10
This was expected. However, the idea that all reference type objects are passed by reference is not really accurate and the following proves so. If we change "MyMethod" by adding one line so it becomes as the following:
1
2
3
4
5
| private static void MyMethod(MyClass myClass) { myClass = new MyClass(); myClass.MyInteger = 10; } |
Value before method call: 5
Value after method call: 5
The value of the field "MyInteger" did not change as you might expected. That is because what actually happens when you pass a reference type object to a method is that the reference to that object is copied and the copy is passed to the method. The new copy of the reference points to the same object, so if you make changes in the called method, you will be making changes on the same object. But if you create a newobject in the called method, you will be actually changing the reference value that was passed and making it point to a new object. And whatever changes you make after this step will be irrelevant to the original object.
The following diagrams illustrates what happens in the previous 2 examples.
![]() |
Example 1: What really happens when you pass an object |
![]() |
Example 2: Creating an instance inside the called method |
If you wish to make any changes to the object in the called method and have them all reflected on the original object even if you make a new instance in the called method, then what you need is to pass it by reference. You need to add the keyword
ref
before the object type in the method signature and also when calling the method. The code will look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| class Program { static void Main( string [] args) { MyClass myClass = new MyClass(); myClass.MyInteger = 5; Console.Write( "Value before method call: " ); Console.WriteLine(myClass.MyInteger); MyMethod( ref myClass); Console.Write( "Value after method call: " ); Console.WriteLine(myClass.MyInteger); } private static void MyMethod( ref MyClass myClass) { myClass = new MyClass(); myClass.MyInteger = 10; } } |
No comments:
Post a Comment