2007/10/20

Brainstorm: Reference type, Value type, and Immutable type in C#

Please read the following codes carefully:
Code 1:
public class Form1
{
 int i = 0;
 string s = "Empty";

 private void button1_Click(object sender, EventArgs e)
 {
  M1(i, s);
  MessageBox.Show("i = " + i.ToString() + ", " + "s = " + s);
 }

 public void M1(int inputI, string inputS)
 {
  inputI = 5;
  inputS = "Something";
 }
}
Code 2:
public class Form1
{
 int i = 0;
 string s = "Empty";

 private void button1_Click(object sender, EventArgs e)
 {
  M1();
  MessageBox.Show("i = " + i.ToString() + ", " + "s = " + s);
 }

 public void M1()
 {
  i = 5;
  s = "Something";
 }
}
What will the MessageBox show of Code 1 and Code 2 separately? Don't copy and paste those codes to your IDE (Visual Studio 2003/2005 or SharpDevelop) now, try to compile and run it in your brain first. This small test can examine your concepts of Reference type, Value type, and Parameter passing in C#. As everyone knows, "int" is a value type, and "string" is a reference type. Let me explain the Code 1 first.

In Code 1, we pass two variables i and s to the method M1 and change their value. Since Value type is passed by value and Reference type is passed by reference, the result should be "i = 0, s = Something". Unfortunately, it's incorrect. The result will be "i = 0, s = Empty". Why? Don't forget "string" is an immutable type. We pass the string s to the variable inputS, so inputS has the same reference (address) of the memory location, which contains the value "Empty", with the variable s. Until now, inputS and s are pointing to the same memory location. When we change the value of inputS, CLR actually create a new memory block which contains the new value "Something" and assign the new reference to inputS. Now inputS and s are pointing to the different memory location: inputS points to "Something", and s still points to "Empty". Now you know why the result is "i = 0, s = Empty".

How about Code 2? To cut a long story short, the correct answer is "i = 5, s = Something". Why? Because we didn't pass i and s to M1, we modified them directly in M1. Although s is immutable, but it will still get the new reference of "Something".

Confused? Don't worry, there is an excellent article talking about this topic: Parameter passing in C#. However, if you are too busy (or too lazy) to read that article, you can go to see this. It's a very good and an easy understanding article, and it also recommended by Jon Skeet, the author of Parameter passing in C#.

PS: When boxing a value type, it will become a reference type plus immutable type, just like string.

No comments:

Post a Comment