Personal Web & Sample Site
Skip Navigation Links
HOME |
About Me |
Articles
| Contact Us
C Sharp Part Two
Rating: 9 user(s) have rated this article Average rating: 5.0
Posted by: joet, on 9/18/2011, in category "C#"
Views: this article has been read 3859 times
Location: Houston, Tx, United States
Abstract: Now, one of the first and most important things I learned about Object Oriented Programming and working with Microsoft C#, is the difference between value types and reference types, and how variables of each type are organized in memory. Also, what effect does this have on the behavior of variables used as parameters. For now, I know if I declare i as an int and assign it the value of 42, and then declare another variable called copyi and assign it i, it copies i into another block of memory on the stack and you now have to blocks of memory (on the stack) that contain the same value of 42.

 

 

Now, one of the first and most important things I learned about Object Oriented Programming and working with Microsoft C#, is the difference between value types and reference types, and how variables of each type are organized in memory. Also, what effect does this have on the behavior of variables used as parameters. For now, I know if I declare i as an int and assign it the value of 42, and then declare another variable called copyi and assign it i, it copies i into another block of memory on the stack and you now have to blocks of memory (on the stack) that contain the same value of 42.

The effect of declaring a variable C as a Circle(the name of a class) is very different. When you declare C as a Circle, c can refer to a Circle object. If you declare refc as another Circle, it can also refer to the same Circle object. If you assign C to refc, refc will refer to the same Circle object that C does; there is only one Circle object, and refc and C both refer to it. So what happens here is that compiler has allocated two blocks of memory, one for C and one for refc on the stack and has assigned an address(reference) that points to the same location in memory that stores the actual Circle object(on the heap).

 

Figure 2 - Value Types and References

 

 Let me explain further how this works;

First, computer memory is organized through the operating system and runtimes that frequently divide the memory used for holding data in two seperate chunks, each of which is managed in a distinct manner. These two chunks of memory are traditionally called the Stack and the Heap, and they serve two very different purposes. You need to know what's going here to fully understand the differences between value types and reference types.

For value types the compiler generates code that allocates a block of memory big enough to hold it value. For a reference type it allocates enough memory to hold the address, or reference to th newly created object.  For example, int is allocated 4 bytes of memory or 32 bits. So when I assign i the value 42, it's copied into this block of memory called the stack. When you instaniate a class to create an object using the new keyword, the memory required to build the object is always acquired from the heap.


 

Note: All value types are created on the stack and all reference types(objects) are created on the heap.(although the reference itself is on the stack). Strings and Nullable types are reference types...

Take the following example written in a "try" "catch" code blocks (more on exception handling later):

 

//We have class name "Program.cs" with main entry point.

Using System;
Using System.Collections.Generic;
Using System.Text;
 
 
namespace Parameters
{
       statice void Entrance()
          {
             int i=0;
            Console.WriteLine(i);
            Pass.Value(i);
            Console.WriteLine(i);
          }
       static void Main(string[] args)
         {
            try
           {
                Entrance();
            {
            catch )Exception ex)
              {
                   Console.WriteLine(ex.Message);
               }
            }
        }
}

//Here we have another class named "Pass" with a method called "Value".

namespace Parameters
{
     class Pass
        {
          public static void Value(int param)
            {
               param = 42;
            }
         }
     }
}

If you run this code it will write o(zero) to the console twice. Why? I declared i as an int and assigned it the value o. I created a method called "Value" for the "Pass" class and gave the method a parameter of int (a value type) and called it param and then assgned param the value "42". So when I called the "Pass.Value" method why wasn't the value "42" written to the console window? How method parameters behave depends on whether they are value types or reference types.

Now add the following class to the project and call it "WrappedInt" with a public instance field called "Number" of type "int" like this: (Note* Fields are variables in OOP)

namespace Parameters
{
   class WrappedInt
    {
      public int Number;
    }
}

Now let's go back to the "Pass" class and add the following public static method and call it "Reference":
 
public static void Reference(WrappInt param)
{
   public int Number;
}

Now, go back to the Program.cs file and add the following statements:
 
#region
Using directives
using System;
using System.Collections.Generic;
using System.Text;
#region

namespace Parameters
{
     static void Entrance()
      {
        int i = 0;
        Console.WriteLine(i);
        Pass.Value(i);
        Console.WriteLine(i);

        WrappedInt wi = new WrappedInt();
        Console.WriteLine(wi.Number);
        Pass.Reference(wi);
        Console.WriteLine(wi.Number);


      }
static void Main(string[] args)
{
    try
    {
      Entrance();
    {
    catch (Exception ex)
      {
       Console.WriteLine(ex.Message);
      }
    }
   }
}

Run the application and this time it will write 00042 to the console window. What happened here? First of all, if you don't provide a constructor the compiler will provide one for your automatically initialized to 0. That explains the 3rd zero. The wi variable is then copied as an argument to the Pass.Reference method. Because WrappedInt is a class(a reference type), wi and param both refer to the same WrappedInt object. Any changes made to the the contents of the object through the param variable in the Pass.Reference method are visible by using the wi variable when the method finishes.

Note: As you should know by now it's common practice to always initialize your variables.
That Said: A class requires a constructor, or default constructor to perform any initialization required. If you don't provide one the compiler will write one for you. Keep in mind that the constructor is basically a special method thats used to initialize fields in a class. So the default constructor method can be overloaded just like the .ToString class or the WriteLine class that has multiple overloads (or implementations) you to can overload the default constructor.

Later, I will get into the following topics:

  • Encapsulation
  • Inheritance (Base Classes and Derived Classes)
  • Virtual Methods/Polymorphism)
  • Enumerations (Enums)
  • Abstract and Sealed Classes
  • Collection Classes and their Interfaces
  • Way more C# down the road so stay tuned....

References:

More later........

When I get back around to this page I will talk about boxing, unboxing, casts, and safe casts and the "ref" and "out" keywords.

 


How would you rate this article?

User Feedback

Post your comment
Name:
E-mail:
Comment:
Insert Cancel

Copyright © 2013 Jose M. Tamez
Last Updated August 18th 2013