Review: References

The goal for this exercise is to make sure that you can use the material that has been covered in the previous exercises, but in a more open-ended (and therefore more ‘real-world’-like) scenario

Thus far, you've seen both reference types, and what are known as simple types

Further, there are a number of other differences, which are summarized below.

You may find it useful to search the web for more information.  In particular, this website
 
(http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91 ) seems to be fairly informative about the differences between memory allocated on the call stack vs. memory allocated in the heap.

Simple types vs. reference types

Always copied by value

// create a space in memory to hold

// an integer

int anInteger;

 

// create another space in memory

// to hold an integer

int anotherInteger;

 

anInteger = 0;

anotherInteger = 10;

// Integers are initialized

 

anInteger = anotherInteger;

// There are now two memory spaces

// the number 10 in each one

 

Always copied by reference

// create a space in memory to hold

// a refernce to a ProgramLogic

// NOTE: WE HAVEN'T CREATED THE

// PROGRAMLOGIC OBJECT YET!!!

ProgramLogic pl1;

 

// create another space in memory to hold

// a refernce to a ProgramLogic

// NOTE: WE HAVEN'T CREATED THE

// PROGRAMLOGIC OBJECT YET!!!

ProgramLogic pl2;

 

pl1 = new ProgramLogic();

pl2 = new ProgramLogic();

// Initialize the references - they

// now each refer to a separate instance

// of the ProgramLogic class.

// Thus, we've got FOUR blocks of memory

// being used

// #1 for pl1

// #2 for the ProgramLogic that pl1 refers to

// #3 for pl2

// #4 for the ProgramLogic that pl2 refers to

 

pl1 = pl2;

// pl1 & pl2 now refer to the same object

// the object pl1 WAS refering to will be

// garbage collected (unless something else is

// still refering to it) since pL1 now points

// to the same object as pl2.

 

 Always passed by value

class SimpleVsReference
{

static
void Main()
{
    // SIMPLE TYPES ARE PASSED BY VALUE

    //  (to methods):

    int theNum = 0;
    Console.WriteLine("Prior to calling the function: {0}", theNum);
    PassByValue(theNum);
    Console.WriteLine("After to calling the function: {0}", theNum);


public
static void PassByValue(int x)
{
    // at this point, there's now two

    //  blocks of memory holding

    // the value 0. They are:
    // theNum (in main)
    // x (in this method - PassByValue)

 

  Console.WriteLine("Passed in: {0}", x);
    // let's try to change it
    x = 10;

  Console.WriteLine("Changed to: {0}",x);
}

}
 

OUTPUT:

Prior to calling the function: 0

Passed in: 0

Changed to: 10

After calling the function: 0

 

 

Always passed by reference

class SimpleVsReference
{

static
void Main()
{
    // REFERENCE TYPES ARE PASSED BY

    //  REFERNCE (to methods):

    ProgramLogic pl = new ProgramLogic();

    // pl has been created, AND we've create an

    // object of type ProgramLogic

    // for it to refer to.  ProgramLogic's

    // constructor

    // initialized the new object to contain 0


    Console.WriteLine("Prior to calling the function: {0}", pl.ToString() );

    PassByRef(pl);
    Console.WriteLine("After to calling the function: {0}", pl);
 
   // This last time, we left off the "ToString", since C# will
    // call that for us.
}

public
static void PassByRef(ProgramLogic obj)
{
    Console.WriteLine("Passed in: {0}", obj.ToString());
    // let's try to change it
    obj.Data = 10;

    Console.WriteLine("Changed to: {0}", obj.ToString());
}

}

OUTPUT:

Prior to calling the function: ProgramLogic object containing: 0

Passed in: ProgramLogic object containing: 0

Changed to: ProgramLogic object containing: 10

After calling the function: ProgramLogic object containing: 10

 

Always has a valid value

 

// SIMPLE TYPES ALWAYS HAVE A VALID VALUE
int
integer; // technically, C# has
        // initialized this with a 'zero'
        // However, we're not allowed to
        // use it before assigning it
        // a value

integer = 0;
// 0 is a valid integer
Console
.WriteLine("integer: {0}", integer);
integer = 10;
// 10 is a valid integer
Console
.WriteLine("integer: {0}", integer);
integer = -10;
// -10 is a valid integer
Console
.WriteLine("integer: {0}", integer);

OUTPUT:
integer: 0
integer: 10
integer: -10

 

OUTPUT FROM RIGHT COLUMN:
theLogic:
theLogic is null!
ProgramLogic object containing: 0

 May be null, indicating that there's no currently valid reference.

 

 // REFERENCES MAY OR MAY NOT HAVE A VALID VALUE
// References either refer to an object
// (and instance of a class), or else
// they can have the value null,meaning
// that the reference is NOT VALID (i.e.,
// it doesn't refer to a valid object)

ProgramLogic theLogic; // technically, this
// has the value null, but still needs
// to be assigned a value before use

theLogic = null;

// theLogic now refers to nothing

// If we attempt to dereference it, the program
// will crash
// To dereference theLogic, we try to get to
// one of it's parts - data, property,
// or method - using the dot operator:
// theLogic.Data = 0; // uncomment this line

// & see what happens


// Console.WL is smart enough
// to check for null:

Console
.WriteLine("theLogic: " + theLogic);
if
(null == theLogic)
{
    Console.WriteLine("theLogic is null!");
}

else

{
    Console.WriteLine("theLogic is NOT null: " + theLogic);
}


// We can reuse the REFERENCE, so that
// it now refers to something else:

theLogic = new ProgramLogic();


// theLogic now refers to a new object
// of type ProgramLogic

theLogic.Data = 0;

Console
.WriteLine(theLogic);

 

 

What you need to do for this exercise:  

For this exercise, you're not required to produce anything, but you are required to read this material (including, and especially, the code examples) in detail, and to understand them.  The most important part is probably the section on how reference variables can have the value null, indicating that the reference is not valid.

I'd recommend examining the sample project, and playing around with the code (for example, stepping through the examples using the debugger, tweaking the code to achieve different results, etc, etc)

 In a future lesson, you'll see how to create your own value types / simple types (called structs), and so it's important to start building up an understanding of how they differ from classes (from reference types), so you can hit the ground running at that point.