Value Types & Reference Types – In C# (Part I)

Along with your C# learning process you have been working with different types, You maybe a starter so you just used primitive types (e.g., int, string, double, ..etc), Exposed some functionality within a specific type (e.g., Console.WriteLine() ), Or you maybe gone deeper and have been creating your own types and instantiating objects from it. So you should have been noticed that in C# it’s all about types, I’m sure also that the you’ve at least seen the term (Value & Reference Types) or having some knowledge of it, From my point of view understanding the difference between Value & Reference Types is critical important for any .Net Developer.

In this blog post I’ll explain the differences between Value Types & Reference types and I’ll try to cover most parts of these two concepts hope you will enjoy reading it ^^ Kindly if you have any questions comment it down and I’ll be glad answering it once I’m available.

So you learned how to create your own types to represent set of data and behavior, And you have been creating objects from these types to hold data and to expose it’s functionality. I think you declared these various types using the “class” keyword. If that’s right so you have declared a Reference Type, Any Type you create using “class” keyword is a Reference Type, Figure 1 will show you an example.

//Figure 1 - Creating Class Example
class Person
    {
        //Instance Fields
        private string name;
        private int age;

        //Instance Constructors
        public Person()
        {

        }
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        //Properties
        public string Name
        {
            get { return name; }
            set
            {
                if(!string.IsNullOrEmpty(value))
                  name = value;
            }
        }

        public int Age
        {
            get { return age; }
            set
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException("Age", "A Person Age Cannot Be Less Than 0.");
            }
        }

        //Instance Method
        public void DisplayName()
        {
            Console.WriteLine(Name);
        }
    }

let’s analyze the code shown above. We have a very simple Type called Person which have some instance fields, methods and properties, Person type is a Reference Type because it’s created using “class” keyword. Until now everything you have seen should be very clear to you. But you should have to know somethings that happens when you work with Reference Types ?

  • Memory allocated from the Managed Heap.
  • Variable contains pointer to the Instance in Managed Heap.
  • Any Reference Type Object has two overhead members that have to be initialized.
  • Bytes for the instance fields are Zeroed out.
  • Garbage Collector may occur to free the memory when the object is unused.

Okay great, i think you now saying “So What” but think for a moment if every time you create a small int a memory allocation occur and initialization of two overhead members occur and that you’ll have to wait GC to free out the memory used by this int and whenever you need to manipulate this int a pointer dereference occurs. It wont be good for your application performance, Actually it will be horrible for your application performance. That’s why the .Net Framework offers Value Types which are lightweight types, according to the previous speech of Reference Types what is the difference working with Value Types?

  • Value Types Instances allocated directly in the Thread Stack not in the Managed Heap.
  • Variable contains the value of the instance.
  • It has no overhead members.
  • When the instance is unused it’s removed directly from the stack (GC doesn’t need to occur).

Wow that’s great so why we don’t use Value Types always instead of classes ? The answer to this question is coming below by the end of this topic ^^ let’s check Figure 2 which shows an example of creating a Value Type.


//Figure 2 - Creating Value Type

struct VPerson
    {
        //Instance Fields
        private string name;
        private int age;

        //Instance Constructors
        public VPerson(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        //Properties
        public string Name
        {
            get { return name; }
            set
            {
                if(!string.IsNullOrEmpty(value))
                  name = value;
            }
        }

        public int Age
        {
            get { return age; }
            set
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException("Age", "A Person Age Cannot Be Less Than 0.");
            }
        }

        //Instance Method
        public void DisplayName()
        {
            Console.WriteLine(Name);
        }
    }

Okay now a Value Type called VPerson (V for Value Type) that have almost everything like the Person class, But hey where is the parameterless constructor that was in the Person class ? Well as Value Types considered lightweight Types it has some limitations compared to Reference Types that i’ll cover but first let’s use our two Types so you can better understand the differences between both Types.

        //Figure 3 - Reference Types Vs. Value Types
        static void Main(string[] args)
        {
            Person p1 = new Person("Ibrahim",24); // Allocated In Heap
            VPerson vp1 = new VPerson(); // Allocated On Stack
            vp1.Name = "Nada";
            vp1.Age = 19;

            Person p2 = p1; //Reference (pointer) Copy
            VPerson vp2 = vp1; //Value Copy

            p1.Name = "Hema" //Change p2 Name as well
            vp1.Name = "Nody" //Doesn't change vp2 Name

            Console.WriteLine(p1.Name); //Displays Hema
            Console.WriteLine(p2.Name); //Displays Hema
            Console.WriteLine(vp1.Name); //Displays Nody
            Console.WriteLine(vp2.Name); //Displays Nada
        }

Okay here our Main method where we use our Person and VPerson types, In Line 4 Person object is allocated in managed heap and pointer saved to variable p1 (Shown in Figure 4), In Line 5 VPerson object allocated in Thread-Stack but wait a second! There’s no parameterless constructor defined in VPerson so an error should occurs. Well no a Value Type Implicitly define a parameterless constructor that set all instance fields to 0/null depending on the field’s type, However you can’t explicitly define parameterless constructor. Reference Types only implicitly define a parameterless constructor in case that you haven’t define any constructor so if VPerson was a class an error was to occur. Okay in line 6 & 7 we set values for vp1 which will be changed directly on the stack (No pointer Dereference), however if we used the same syntax to change p1.Name or p1.Age a pointer dereference will occur to do such a thing. In Line 9 we create p2 Variable of type Person and assign p1 to it what’s actually happens that p1 reference to the Person object on the Heap copied to p2 variable so no memory allocation for new object occurred just the reference is copied so the two variables are pointing to the same object. Line 10 looks similar but it’s not because VPerson is a value type a new instance is allocated on the stack for vp2 and vp1 instance fields values are copied to vp2 instance fields, So now vp1 & vp2 are holding two different instances unlike p1 & p2. Line 12 & 13 Changes p1, vp1 Name respectively of course you should have knew that in p1 a pointer dereference occur because it’s Reference Type, But in vp1 the value changed directly from the stack. Line 15 & 16 displays p1, p2 Name property respectively and Wow both show same result which is “Hema” however we changed p1.Name only, That happened because both variables hold a reference to the same instance so change in one reflects on the other. Line 17 & 18  displays vp1, vp2 Name property respectively but it shows “Nada” then “Nody” wired!! No it’s not, Because vp1, vp2 are Value Types they are holding two different instances of VPerson Type even when we assigned vp1 to vp2 in Line 10 a whole new Instance allocated on the stack and only values of the instance fields are copied to the newly created instance. Check Figure 4.

Reference Types Vs. Value Types Figure 4

I know these concepts are confusing somehow at the beginning but it’s really very important to understand it, I assume that you knew what’s Value Types and how you create it and you understood some differences compared to Reference Types i’ll explain more differences in depth in the next part of this post, but for now you have the good knowledge you need to start exploring the Value Types yourself ^^. The preceding table is a summary of what i’ve explained already and what i’ll explain in the next part regarding differences between both Types.

Reference Types Compared To Value Types
Comparison Key Reference Types Value Types
Allocated On Managed Heap Thread-Stack
Variable Contains Pointer to the instance The instance itself
Keyword Used ”class” ”struct” Or “enum” (For Enumerated Type)
Implicitly Derived From System.Object
  • For “struct” System.ValueType which itself derived from System.Object
  • For “enum” System.Enum which itself derived from System.ValueType
Can Explicitly Choose Base Type Yes No
Can Be Used As A Base Type Yes No (Implicitly Sealed)
Can Implement Interfaces Yes Yes
Passed As Argument To Method Copy of the pointer is passed New Instance is created on the stack and fields values are copied to it
Assigning Variable To Another Copy of the pointer New instance is created on the stack and fields values are copied to it
Instance Field Manipulation Pointer dereference occurs Manipulated directly from the stack
Boxed & Unboxed Forms Always Boxed Unboxed And Boxed
Single Instance Can Be Shared Yes No
When Instance Is Unused Wait for GC to occur to free its memory Memory allocated is freed immediately
Explicitly Define Parameterless Constructor Yes No (But always defined implicitly)
Can Define Multiple Constructors Yes Yes (You have to initialize all instance variable to initial value in constructor body)
Can Define Static Constructor Yes Yes

Hope you enjoyed the post and understood it very well ^^ Kindly if you have any question comment it and i’ll reply all your answers ^^ And wait for the next part very soon.

Advertisements

One thought on “Value Types & Reference Types – In C# (Part I)

Leave a Reply

Fill in your details below or click an icon to log in:

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