Tuesday, June 24, 2008

Reference Types and Value Types

Programming Language: C#
Type: Tutorial
Level: Beginners
Topic Category: General Programming
Main Series: Introduction to programming in C# and the .NET framework
Topic Title: Reference vs. Value Types


As we mentioned previously, in c#, everything is a class. However, there are five types of classes in C# and those are: class, struct, enum, delegate and interface. When I say they all are classes, that is in the .net framework, interfaces are actually abstract classes and that's how they are implemented in the level of MSIL (although text MSIL has a modifier that marks a class as an interface/struct ... etc, they are all declared as .class declarations)

C# allows three kinds of data types:
  • Reference Types
  • Value Types
  • Pointer Types (Yes C/C++ programmers, it is pointer types alright)
Pointer types are only allowed in unsafe contexts and are thus not managed by the CLR. Therefore we will not discuss them until we do unsafe code.

Value Types are types designed usually to hold single "values" as the name emplies. Now, when we say single, we don't mean a single simple type value. What we mean is that value type objects will hold a value rather than a real object. The destinction is unclear, I know, and it never will be because it's in the eyes of the programmer. For example a point might be thought of as a value, also size in terms of width, height and depth might be thought of as a comopund value. However, not all cases are as clear as the size case, consider a rectangle type, can we treat a rectangle as a value or should we treat it as an object. Value types however, have technical features that we will discuss later. struct and enum types are Value Types. All value type classes are automatically inherited (either directly or indirectly) from System.ValueType

Reference Types are types designed usually to hold objects that are "active" in some since. For example a Vehicle type will be needed for more than just to store the data of a car. Again, it is relative in some cases. class, interface, and delegate types are all reference types.

Now let's suppose we have a type DataType, and that we write the following code:
DataType p = new DataType();
Now, if we write the following line of code immediatly after the former:
DataType q = p;
The thing to note about reference types and value types is the way assignment works on both types. So, if DataType was a value type what will happen is that a copy of p will be assigned to q. That is, there will be actually two DataType objects in memory with the same value.
However, if DataType is a reference type, what will happen is what we call reference assignment. That is, the q reference will be assigned the same object as reference p making two references p and q point to the same object. This means only one DataType object will be in memory. Now changing p won't change q in the first case (value types). It will change both p and q in the second case (reference types).

Below is a comparison between reference and value types, characterizing the main features of each kind of types and the difference between them:

Reference TypesValue Types
Holds reference to an object in memory
Holds a value in memory
Assignment of two references will make them point to the same object in memory
Assignment of two value type objects will copy one to the other, keeping two separate objects in memory
Declaring a reference does not automatically create an object for it
Declaring a value type object automatically creates an object in memroy
class, interface, delegate
struct and enum
Usually used for active objects, those which will need to perform various operations and interact with other objects
Usually used for creating value holding types (types from which objects will be able to hold values)
Sample candidates:
Vehicle, Product, SaleItem, Delivery, Queue, Student, GraphicalShape, GeometricalShape, DataBase, NetworkMessage, ChatControl, BlogController
Sample candidates:
Size, Volume, Area, PersonName, PhoneNumber, EmailAddress, MailingAddress, IpAddress, IpConfigurations, BlogSettings
Can be assigned a null value (a reference pointing to nothing - actually null is called nothing in VB.NET)
Can not be assigned a null/nothing value unless made nullable

Sometimes we need to treat value types as reference types. This is done in an operation called boxing and it simply involves casting the value type value into an Object reference:
int i =10;
object o1 = i; //Implicit boxing
object o2=(object)i; // Explicit boxing
It is important to understand the difference between reference and value types to fully understand the difference between structs and classes and to know when to use which.

The following built-in types in C# are value types:
short, int, long, ushort, uint, ulong, byte, sbyte, float, double, decimal, bool, char, struct, enum
The default values for these types are 0's representation for numeral types, false for bool, the value produced by casting 0 to the enum type for enums, '\0' for char, the value produced by setting all value-type fields to their default values and all reference-type fields to null for structs

I included links to other materials/references/articles on reference and value types for more information:

No comments: