Monday, October 24, 2011

- C# Programming Constructs 2

Parameter Modifiers:
  • None : Pass by value, the method will receive a copy of the original data.
  • out : Pass by reference however this parameter must be assigned by the method being called otherwise a compiler error will be issued.
  • ref : Pass by reference and must be initialized before it passed to the method (reassigning by called method is optional)
  • params: Send in a variable number of arguments as a single logical parameter. A method can have just a single params and it must be the final parameter of the method
let's go through a simple example :

static void Main(string[] args)
{
    int result;
    int num = 20;
    Add(ref num, 20, out result);// num = 100 and result = 40
    int sum;
    sum = AddAll(4, 3, num, result);// sum = 147
}

static void Add(ref int num_1, int numb_2, out int result)
{
    result = num_1 + numb_2;
    num_1 = 100; //since it is ref the value of the num in below will be changed
}

static int AddAll(params int[] nums)
{
    int sum = 0;
    for (int i = 0; i < nums.Length; i++)
        sum += nums[i];
    return (sum);
}

Optional Parameters : .NET 4 allow programmers to create methods which can take optional arguments. However the value assigned to an optional parameter must be known at compile time and can not be resolved at runtime (compile time error if you attempt to do so). further more to avoid ambiguity optional parameters must be packed onto the end of a method signature (otherwise compiler error).

static void SetName(string name = "John Smit"){}
above method can be called with or wihout arguments:
  • SetName();
  • SetName("Mehdi");
Named Parameter : Allow you to invoke a method by specifying parameter values in any order thus  in order to pass a parameter you need  to specify each parameter by name using colon operator. Named arguments must always be packed onto the end of a method call. Example:

static void SetData(string name , int age, string job){}

One way to invoke the above method using named parameter:

SetData(job: "software engineer", name: "mehdi", age: 29);

Method Overloading:
When you define a set of identically named method that differ by the number or type of parameters. Example:

static int Add(int num1, int num2){}
static double Add(double num1, double num2){}

C# Arrays:
Array is a set of data items, accessed using a numerical index. You may initialize the array in stage of declaration otherwise it will set to the default value. new keyword is optional when you use "{}" for initialization.

//an array of int with 4 elements (index 0 to 3)
int[] nums = new int[4];
//Array of string wth 3 elements
string[] birds = new string[] { "bluejay", "dock", "goldeneye" };
//same as previous arry with different syntax
string[] birds = { "bluejay", "dock", "goldeneye" };

var elements = new[]{1,2,3};

Keep in mind  var array can support just one type at a time. However if you need an array to store variety of types you might use object array as following example

object[] elements = new object[5];
elements[0] = "hi";
elements[1] = 2;
elements[2] = false;
elements[3] = DateTime.Now;
elements[4] = 333.333;
foreach (var item in elements)
{
    Console.WriteLine(item);
}

Multidimensional Arrays:
  • Rectangular array : An array of multiple dimensions, where each row is of the same length.
  • Jagged array : Contains some number of inner array, each of which may have a different upper limit
//rectangular array
int[,] rectangualrArray;
rectangualrArray = new int[5, 5];
//assign a value to multidimensional array
rectangualrArray[2, 3] = 999;

//jagged array (an array of 3 different array)
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[2];
jaggedArray[1] = new int[7];
jaggedArray[2] = new int[5];

Arrays also can be used as arguments or return values:

static void PrintAll(int[] all_nums) { }//array as parameter
static string[] GetAll() { }//array as return value

All array gather much of its functionality from the System.Array class. Some member of System.Array have listed below: For more info refer to Array Class in MSDN
  • Clear() : Sets a range of elements in the array to empty.
  • CopyTo() : Copy elements from the source array into the destination array.
  • Length : Returns the number of number of items within the array.
  • Rank : Returns the number of dimensions of the current array.
  • Reverse() : Reverse the contents of an one-dimensional array.
  • Sort() : Sorts a one-dimensional array of intrinsic type. (array must implement the IComparer interface)
static void Main(string[] args)
{
    string[] my_array = { "Item_1", "Item_2", "Item_3" };
    PritOut(my_array);
    //reverse the array
    Array.Reverse(my_array);
    PritOut(my_array);
    //clear the second item
    Array.Clear(my_array, 1, 1);
    PritOut(my_array);
}

static void PritOut(string[] string_array)
{
    foreach (var item in string_array)
    {
        Console.Write(item + ", ");
    }
    Console.WriteLine();
}
System.Array method output exmple
Enum Type:
Set of symbolic names that map to known numerical value, which are user-defined data type. Here is an example to illustrate the use of enums:

enum DaysOfWeek
{
    Monday,     //0
    Thursday,   //1
    Wednesdays, //2
    Thursday,   //3
    Friday,     //4
    Saturday,   //5
    Sunday,     //6
}

By default, first element is 0, fallowed by an n+1 progression. However you are allowed to change the initial value. Enumerations do not need to have unique values neither fallow a sequential ordering (below example). further more you are allowed to change the underlying storage for an enum, which may comes handy when you dealing with low-memory devices (The default storage type is int). As an example I change the underlying storage for below enum to bye.

enum DaysOfWeek: byte
{
    Monday = 55,    //55
    Thursday,       //56
    Wednesday,      //57
    Thursday,       //58
    Friday,         //59
    Saturday = 54,  //54
    Sunday,         //55
}

Note: Since Monday and Sunday they got the same repetitive value you might get unexpected output in some case such a below.

Console.WriteLine(DaysOfWeek.Sunday); //output : Monday

You can declare a enum variable like this:

DaysOfWeek my_day = DaysOfWeek.Sunday; //Declaring Enum Variable

System.Enum Type: provides methods to interrogate and transform a given enumeration.

Console.WriteLine(Enum.GetUnderlyingType(my_day.GetType())); // output: System.Byte
Console.WriteLine(typeof(DaysOfWeek)); //output: BasicDataTypes.Program+DaysOfWeek

Enum's Name/Value Pairs:

Console.WriteLine("{0} = {1}", my_day, (byte)my_day); //output : Monday = 55

In order to see the name you may use the enum variable just like the above example or use the ToString() method  : my_day.ToString()

Array enumData = Enum.GetValues(my_day.GetType());//get all name/value pairs
for (int i = 0; i < enumData.Length; i++)
{
    Console.WriteLine(enumData.GetValue(i));
}


DayOfWeek and ConsoleColor are enums in the System namespace.

Structure Type :
Structure is lightweight class type which provides a way to define a type that supports encapsulation, but not inheritance. Since Structure type implicitly derived from System.ValueType (purpose: to override the virtual methods defined by System.Object to use value based versus reference based, semantic), it will be allocated on stack. example:

struct Size
{
    // Fields
    public int Width;
    public int Height;

    // Display
    public void Display()
    {
        Console.WriteLine("Width = {0}, Height = {1}", Width, Height);
    }

    // Custom constructor.
    public Size(int width, int height)
    {
        Width = width;
        Height = height;
    }
}

Create Structure Variable:

//All fields are needed to be assigned a value before use
Size my_size;
my_size.Width = 100;
my_size.Height = 100;
//or
//Default Constructor
Size my_size = new Size();//Width and Height will be 0
//or
//Custom Constructor
Size my_size = new Size( 100, 100);

C# new keyword will invoke the constructor, If there is no parameter passed the default constructor will be called. The advantage of default constructor of a structure is each piece of field data is automatically set to its default value.

Value Types VS Reference Types:
Value types are allocated on the stack that's why they can be created and destroyed very quickly since it's lifetime is determined by the defining scope. On the other hand Heap allocated data is monitored by the .NET garbage collector and has a lifetime that is determined by a large number of factors.
Value Types are derived from System.ValueType and since they are always sealed can not function as a base to other types. Otherwise reference type can be derived from any type except System.ValueType as long as that type is not sealed.
Assigning value type to another is a member-by member copy of the field which makes them two separates copies. However assigning reference type is redirecting what the reference variable points to in memory

Reference Type Within a Value Type:
In this section we go through an example which a value type contains a reference type to see their behaviors. Below example shows when you change a reference type all the instances which refer to the memory will be affected because both pointing to the same object in the memory (shallow copy).

class SomeInfo
{
    public string Info;
    public SomeInfo(string s)
    {
        Info = s;
    }
}
struct Size
{
    public int Width;
    public int Height;
    public SomeInfo structInfo;
    public Size(int width, int height, string s)
    {
        structInfo = new SomeInfo(s);
        Width = width;
        Height = height;
    }
    public void Display()
    {
        Console.WriteLine("Width = {0}, Height = {1}, Info = {2}", Width, Height, structInfo.Info);
    }
}

static void Main(string[] args)
{
    Size S1 = new Size(100, 100, "S1");
    Size S2 = S1;
    S2.Width = 50;
    S2.Height = 50;
    S2.structInfo.Info = "S2";
    //by changing the value of S2 info value of S1 info will be affected as well
    //since both pointing to the same object in the memory
    S1.Display();
    S2.Display();
    Console.ReadLine();
}


Passing Reference Type by Value: pointing to the same object as caller's object which makes it possible to alter the object's state data but not reassign what the reference is pointing to.Illustrated in below example.

Passing Reference Type by Reference: callee may change the value of the object's state data as well as the object it is referencing. Illustrated in below example.

    class SomeInfo
    {
        public string Info;
        public int value; 
        public SomeInfo(string s)
        {
            Info = s;
        }
        public void Display()
        {
            Console.WriteLine("info = {0} and value = {1}", Info, value);
        }
    }

    static void Main(string[] args)
    {
        SomeInfo info = new SomeInfo("\"Main function Info\"");
        info.value = 0;
        info.Display();
        ReferenceTypeByValue(info);
        info.Display();
        ReferenceTypeByReference(ref info);
        info.Display();
        Console.ReadLine();
    }
    static void ReferenceTypeByValue(SomeInfo info)
    {
        info.value = 1; // change the value of object's state
        //can not reassigning what the reference is pointing to
        info = new SomeInfo("\"ReferenceTypeByVlaue function Info\"");
        info.value = 2;
    }
    static void ReferenceTypeByReference(ref SomeInfo info)
    {
        info = new SomeInfo("\"ReferenceTypeByRefernece function Info\"");
        info.value = 3;
    }



    Nullable Types:
    Value types can never be assigned the value of null if you do so you will encounter compile error. Anyway C# provides a way to use null for value types, by adding suffix of question mark symbol (?). local nullable variables must be assigned an initial value before you can use them.This is really useful in some cases such as relational databases.(Keep in mind you will issue compile error if you use nullable suffix for reference types such as "string". Examples:

    bool? nullable_bool = null;
    int? nullable_int = -1;
    int?[] nullable_array = new int?[5];

    Good to know that ? suffix notation is a shorthand for creating an instance of the generic System.Nullable<T> structure type. HasValue property or != operator can be useful to discover whether the nullable variable has  been assigned a null value. the nullable assigned value can be obtain directly or via the Value property. Above example is shorthand of following example:

    Nullable <bool> nullable_bool = null;
    Nullable <int> nullable_int = -1;
    Nullable <int>[] nullable_array = new Nullable <int>[5];

    By help of ?? operator you can assign a value to a nullable type if the retrive value is null. Which is a compact version of traditional if/else condition.

    //if nullable_int value is null, assign 500 to it
    nullable_int = nullable_int ?? 500;


    Reference: Pro C# 2010 and the .NET 4 Platform by Andrew Troelsen.

    1 comment: