Lately I’ve been thinking about the nuances of the C# language. A friend of mine and I were talking about the merits of C# as compared to Java. Of course, I don’t want to open that can of worms here, however I did realize that I appreciate small details in the C# language that are not present in Java. One of those details is the keywords used in method parameter lists. These include ‘ref’, ‘in’, and ‘out’. The reason these are significant is that in both C# and Java, how are parameters passed? Well we’ve all been told that, of course, parameters are passed by reference and so we go along happily with this information because most of the time for all intents and purposes it is true. But the deeper truth of the matter is that while references are passed, the are actually passed by value.
Here’s is some code to prove it:
public class Person { protected string name; public string Name { set { this.name = value; } get { return this.name;} } protected string email; public string Email { set { this.email= value; } get { return this.email;} } public override string ToString() { return this.name + ", " + this.email; } } public static void main ( string[] args ) { Person p = new Person(); p.Name = "Matt Long"; p.Email = "matt.long@matthew-long.com"; System.Console.WriteLine( p.ToString() ); ChangeMyMembers( p, "Bob Smith", "bob@yyyyy.com" ); System.Console.WriteLine( p.ToString() ); ChangeMe( p, "Wendy Johnson", "wendy@yyyyy.com" ); System.Console.WriteLine( p.ToString() ); } public static void ChangeMyMembers( Person p, string name, string email ) { p.Name = name; p.Email = email; } public static void ChangeMe( Person p, string name, string email ) { p = new Person(); p.Name = name; p.Email = email; }
If you were to run this program, what would you expect the output to be? Here is the actual output:
Matt Long, matt.long@matthew-long.com Bob Smith, bob@yyyyy.com Bob Smith, bob@yyyyy.com
Is that what you expected? Well, since this whole post is about the parameter keywords, I would expect your answer is no. But what happened?
When we passed the Person reference to the ChangeMe() method we passed a copy of the reference. That copy is now only available in the method scope. If we change that reference, it won’t change the original–only that local copy. So when we call p = new Person(); we have assigned that local copy of the reference to point to an actual place in memory, however, it goes away as soon as we leave the method.
Now, to my knowledge there is nothing you can do to address (no pun intended) this behavior in Java directly. In C# however, enter the keyword ‘ref’. If we simply change the ChangeMe() method signature to look like this:
public static void ChangeMe( ref Person p, string name, string email )
And then when we call ChangeMe(), we also use the ref keyword like this:
ChangeMe( ref p, "Wendy Johnson", "wendy@yyyyy.com" );
We now get the output we expected:
Matt Long, matt.long@matthew-long.com Bob Smith, bob@yyyyy.com Wendy Johnson, wendy@yyyyy.com
I am not by my comments here going to enter into a “which language is better” holy war, however, the parameter keywords in C# are a nice feature. Here is an excercise for the reader. Can you implement a swap method in Java? If so, how? How would you do it in C#?
If you need some pointers for the Java way, you can start here: http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html. Then do an Internet search. (Here’s a little hint: you would have to encapsulate the parameters in a class that can be de-referenced in the swap method.)
If you want to learn more about the nuances of C#, a good way to do so is to read some interview questions. Take a look at these here.