Methods, Parameters and Value and Reference Types in C#, a few notes on

This post is based on Chapter 4 of Andrew Troelsen’s “Pro C# 2008 and the .Net Platform” availble from APress.

The out and ref Parameter Modifiers

I am always a bit suspicious of the out modifier as this allows you to move away from the normal state of affairs where a method takes n number of parameters and returns a single value. Using the out param it is possible for a method to return n number of values, all of different type.
Note that if your method does not assign a value to an out parameter you will get a compilation error.

Next up is the ref parameter modifier, which changes the default behaviour of passing params by value. So what does this mean?
It means that normally you hand a method a copy of whatever object you are working with – i.e. you pass parameters by value. Using the ref keyword you are now in stead handing the method a pointer (reference) to the location of your object.

One important implication of the above is that you can pass unassigned variables using the out modifier (as the method is obliged to assign a value to the param) – where as any variable passed by ref (of course) must be instantiated (because you are passing exactly a reference to this instantiated object).

Now – reading up on this actually gave me a major gotcha – because I’ve often noticed that without using the ref keyword you can hand an object over to a method, let the method modify the object properties, and afterward see the changes back in the calling method (on the original object)… so what’s all this stuff about passing parameters by value and the methods working on a copy?
Well, turns out that what you are passing is not a copy of the actual object instance – but rather a copy of the reference to the object instance. Just try and get this clear in your head because it’s slightly odd… when passing an object to a method (without any modifiers like out or ref or anything) you are in fact passing by value a copy of the reference to the  actual object…

What this means is that if you pass a reference type normally (by value) you are able to alter the state of the referenced object (i.e. change properties of this etc), but you cannot alter what the original variable is referencing (because you are working with a copy of this reference). By contrast, if you pass a reference type variable by reference (using the ref keyword) you can alter both the referenced object’s state and change what the original variable is pointing to (e.g. you could assign the reference to a brand new object) because you are now working with the actual reference to the object, and not a copy of this reference.

I’ll leave that with you to mull over for a bit – as you can see – once my explanatory powers run out I will just revert to repeating myself until you yield and admit that you’ve got it! 🙂

The params Parameter Modifier

This one is an odd one, basically this allows you to pass a variable number of parameters of the same data type – but as opposed to a method that accepts an array of some type, you can simply pass in a comma-separated list of values when the params keyword is in place.
For the above reasons a method can only have one parameter marked with the params  keyword, and this must be the last parameter as well (so the compiler can work out when the comma-separated list starts).

Really this is just a convenience for the caller, and probably not something you would (or should) use too much. Under the hood the CLR creates an array from the supplied values.

Enum Types

Enumerations are value types, and by default maps to an Int32 starting a zero, however you can override this by adding the datatype to the Enum declaration like e.g: Enum example : short { … }.
Also you can set the value of each Enum member using the = operator, so e.g: Enum Example : short { First = 10, Second = 20 }

Finally you can work with Enum types in more detail by using the static helper methods GetUnderlyingType(type t) and you can iterate the available enumeration values by using the GetValues(type t) method.

The struct Type

This is usually seen as a kind og light-weight class and are usually used to represent simple atomic entities, often stuff like a Point (with a x and y property). However structs can also be used for much more complicated data structures.
The key guideline for when to use these are that all structs are implicitly sealed and so cannot be inherited from – so use these for simlpe atomic structures. Also note that a struct like an enumeration is a value type, and hence inherits from the ValueType. This means that stucts live on the stack and like e.g. Int32’s they are copied member-by-member.

Value Types vs. Reference Types

So we’re been circling around this a lot in this and the previous post, but what is the real difference?

Well, value types live on the stack and so are destroyed as soon as the variable goes out of scope. Reference types on the other hand live on the heap and wait around for the garbage collector once they have gone out of scope.
So what does this mean when we’re working with variables? Well, if I have a Int32 a and another Int32 b, and I say that a = 10; and then b = a;  I would end up with two independent pieces of data on the stack, each of which can be modified independently. This is called a member-by-member copy, so b becomes a separate entity with all the data copied from a. Subsequently changing b does not affect a, and vice-versa.
If on the other hand I create a reference type variable like objA and objB, set some properties of objA and then set objB = objA; – I actually end up with one object living on the heap, with two references to it. When I assign objB = objA; I am actually copying the reference, not the object. So if I subsequently changed the properties of the object referenced by the objB variable, the changes would of course be reflected in objA (there is only one object).

Finally just remember that even though strings are reference types, then they actually mimic the behaviour of value types. Because strings are immutable, whenever you assign for example strB = strA;  strB actually becomes a reference to a copy of the data referenced by strA. This is a small but important difference, and it means that when we subsequently change strB our strA variable will remain unaffected – not because the string is a value type, but because it will always create new copies of the data referenced whenever assigned or modified in any way.

Finally, finally, if you have a value type like a struct, and contained within this you have a reference type, copying the valuetype will cause the contained reference to be copied (the reference, not the object referenced)…. 🙂 – it makes sense really! This is an effect of what is called a shallow-copy (as opposed to deep or full object cloning, see later discussion of the ICloneable interface and how to implement this).

Also have a look at the discussion of the ref keyword at the beginning of this post.

Nullable Types and the ?? operator

Value types cannot be assigned the value of null – but if you have ever worked with databases you will no doubt have encountered int rows or similar which allow null (foreign keys as an obvious example). To bridge this gap .NET 2.0 introduced the Nullable type, which has static helper properties .HasValue and .Value.

Also we now have the ?? operator which allows you to return a default value if the nullable variable does indeed contain null:

int intId = GetNullableValueFromDatabase() ?? 0; //So if our method returns null, we default to 0
Nullable<int> intId = GetNullableValueFromDatabase(); //However, it's neater to read this into a nullable int and check for HasValue
if(intId.HasValue) { Console.Write(intId.Value); }  //Note that int? is shorthand for Nullable<int> - appplies to all value types.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: