C# reference type behaviour
I have some confusion with reference type following is the test example please tell me how it will works
class TestClass
{
public int i = 100;
}
class MyTestClass
{
public void Method()
{
int i = 200;
var testClass = new TestClass();
testClass.i = 300;
Another(testClass, i);
Console.WriteLine("Method 1:" + testClass.开发者_运维知识库i);
Console.WriteLine("Method 2:" + i);
}
public void Another(TestClass testClass, int i)
{
i = 400;
testClass.i = 500;
testClass = new TestClass();
//If we have set here again testClass.i = 600; what should be out putin this case
Console.WriteLine("Another 1:" + testClass.i);
Console.WriteLine("Another 2:" + i);
}
public static void Main()
{
MyTestClass test = new MyTestClass();
test.Method();
Console.ReadLine();
}
}
***EDIT****** What should be the Output of this,and how many times the Object of the TestClass() will created during execution.
The output should be:
Another 1:100 Another 2:400 Method 1:500 Method 2:200
C# passes by value unless the ref
keyword is used. For value types the value is copied. For reference types the value of the reference is copied.
The variable i
is completely unrelated to testClass.i
. I'll look at the simple case first, i
is an int - a value type. When you call the method Another
with i
as an argument it is passed by value so modifying the value of i
inside the method Another
it does not change the value of the variable i
in Method
- it is equal to 200 all the time.
The value of variable testClass
is also passed by value, but in this case because it is a reference type the value of the reference is passed and so the variable testClass
in Another
initially refers to the same object as the variable in Method
. When you modify the value of testClass.i
in Another
it changes the object you created in Method
so that it's member is set to 300.
Then this line creates a new and unrelated object:
testClass = new TestClass();
Sometimes it is easier to see what happens in a diagram, where the top row shows variables and the bottom row shows the objects they refer to:
Before assignment: After assignment: +-------------+ +-------------+ +-------------+ +-------------+ | Method | | Another | | Method | | Another | | testClass | | testClass | | testClass | | testClass | +-------------+ +-------------+ +-------------+ +-------------+ | | | | | | | | v | v v +-----------+ | +-----------+ +-----------+ | TestClass |<-----------+ | TestClass | | TestClass | | i = 300 | | i = 300 | | i = 100 | +-----------+ +-----------+ +-----------+
So the value of testClass.i
when printed in Another
is the default that is set in the constructor, i.e. 100. The assignment does not modify the original object. You are only reassigning the variable to point to something else.
In C# anything that is a struct is a value type, anything that is a class is a reference type. When you pass a value type as a parameter to another method there is no way for the method to alter the original value (unless the value type is passed using the ref keyword). When you pass a reference type as a parameter to another method method any changes the method makes to the object will be reflected in the object upon return from the method. The output would be:
Another 1:100
Another 2:400
Method 1:500
Method 2:200
The i variable in the Another method cannot change the value of the variable i in the Method method, because i is a value type; therefore the value of i in Method (200) is unchanged by your call to Another. TestClass however is a reference type, so Another can alter the field within it, hence in the line:
testClass.i = 500;
changes the value as seen by Method, hence the output of Method 1:500. When you allocate a new instance of TestClass in the line:
testClass = new TestClass();
you have changed what the reference is within Another, but the original instance from Method is no longer available to the method Another, hence anything that another does to its testClass variable will have no impact on the instance the Method is referring to
Basically,
testClass.i = 500;
changes the value inside the object. You are passing this object around, so this change will be seen by everything that has a reference to the object. But
i = 400;
testClass = new TestClass();
these assignments only change the value of a local parameter. This change is not seen by any code outside the same method.
精彩评论