Tuesday, February 28, 2012

Generic Collections

In previous post we talked about Arrays and a special collection object called an ArrayList. We also saw some of the benefits and drawbacks of each approach. Today we will talk about generic collections and how you can use them to create a collection of a specific type and add objects of that particular type to this collection.

We will also talk about how you can pass a collection of any type to a generic method and then inspect the type and do something with it.

Generic Collections
Lets assume you have the following class...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace GenericsTest
{
    public class Sales
    {
        private string _salesAssociate;
        private double _projected;
        private double _actual;

        public String SalesAssociate
        {
            get { return _salesAssociate; }
            set { _salesAssociate = value; }
        }
        public double Projected
        {
            get { return _projected; }
            set { _projected = value; }
        }
        public double Actual
        {
            get { return _actual; }
            set { _actual = value; }
        }
    }
}

Let's create another class...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace GenericsTest
{
    public class Salary
    {
        private string _salesAssociate;
        private double _baseSalary;
        private double _commission;

        public String SalesAssociate
        {
            get { return _salesAssociate; }
            set { _salesAssociate = value; }
        }
        public double BaseSalary
        {
            get { return _baseSalary; }
            set { _baseSalary = value; }
        }
        public double Commission
        {
            get { return _commission; }
            set { _commission= value; }
        }
    }
}

Let's build a collection of these objects. We will create two generic collections - each of specific type i.e. Sales and Salary. Notice, that since the collection is of specific type, you cannot mix and match the objects. Although there are ways to do that, but we will cover it in future posts.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace GenericsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //declare generic list of type sales
            List<Sales> lstSales = new List<Sales>();
            List<Salary> lstSalary = new List<Salary>();

           //lets add few objects to these collections
            Sales oSales = new Sales();
            oSales.SalesAssociate = "Mike Smith";
            oSales.Projected = 1000;
            oSales.Actual = 1150;
            //Add to collection
           lstSales.Add(oSales);

           //add another object
            Sales oSales1 = new Sales();
            oSales1.SalesAssociate = "Patty Smith";
             oSales1.Projected = 1200;
            oSales1.Actual = 1350;
            //Add to collection
            lstSales.Add(oSales);

           //lets add few objects to another collection
            Salary oSalary = new Salary();
            oSalary.SalesAssociate = "Mike Smith";
            oSalary.BaseSalary= 500;
            oSalary.Commission= 200;
            //Add to collection
           lstSalary.Add(oSalary);

           //add another object
            Salary oSalary1 = new Salary();
            oSalary1.SalesAssociate = "Patty Smith";
            oSalary1.BaseSalary= 500;
            oSalary1.Commission= 275;
            //Add to collection
           lstSalary.Add(oSalary1);
    
       }
    }
}
          


What if you want to use the same method to pass these collections and do something based on its type. Since every object in .NET inherits from System.Object, you can pass them as object type, but instead we will do something better here.

Let's create yet another class which will do something with these two objects defined above.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;

namespace GenericsTest
{
    public static class DataType
    {
        
        public void DoSomething<T>(List<T> lstData)
        {
           
        if (lstData.GetType() == typeof(List<Sales>))
         {

         for (int i = 0; i < lstData.Count; i++)
         {
        Sales oSale = (Sales)Convert.ChangeType(lstData[i], typeof(Sales));
        Console.WriteLine(String.Format("Sales Associate:{0},Projected Sales:{1},
        Actual Sales:{2}",oSale.SalesAssociate, oSale.Projected,oSale.Actual));                   
        Console.WriteLine(Environment.NewLine);            
         }
       }
       if (lstData.GetType() == typeof(List<Salary>))
       {

       for (int i = 0; i < lstData.Count; i++)
       {
        Salary oSalary = (Salary)Convert.ChangeType(lstData[i], typeof(Salary));
        Console.WriteLine(String.Format("Sales Associate:{0},Salary:{1},
        Commission:{2}",oSalary.SalesAssociate, 
        oSalary.BaseSalary,oSalary.Commission));              
        Console.WriteLine(Environment.NewLine);            
        }
       }
      }
    }
  }

Now all you have to do is pass either collection to this method. You can extend this method to accept collection of other types, like this...

DataType.DoSomething(lstSales);
//or
DataType.DoSomething(lstSalary);     


Generics is a very powerful concept which allows for better and more flexible code. Generics, along with reflection which we covered earlier can be a powerful tool.

Thank you.


Sunday, February 26, 2012

Arrays and Arraylist in .NET

So far we have been discussing the fundamentals of object oriented programming, difference between interfaces, abstract classes, enumerations, structures etc. Today, we will talk about using arrays and arraylists to store various objects and difference between the two.

Both arrays and arraylists are stored on a heap. Even if you store value types in an array or an arraylist, the values are implicitly converted to reference types (boxing) and you must explicitly convert them back to proper value types (unboxing) when using them.

Since the items stored in an array or an array list are objects, you can use them to also store reference to objects. For example,

consider the following class...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Student
    {
      
     private string _name;
     private string _address;
     private int _studentID;
     public string Name
     {
          get {return _name;}
          set {_name=value;}
     }
     public string Address
     {
          get {return _address;}
          set {_address=value;}
     }
     public int StudentID
     {
          get {return _studentID;}
          set {_studentID=value;}
     }
  }
    
}

Now let's use an array to store several references of these objects.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //Using an Array
 
            //first instance
             Student student1 = new Student();
             student1.Name = "Student One";
             student1.Address = "123, Peachtree Road, Atlanta, GA 30303";
             student1.StudentID = 1;
            //second instance
             Student student2 = new Student();
             student2.Name = "Student Two";
             student2.Address = "456, Peachtree Road, Atlanta, GA 30303";
             student2.StudentID = 2;
            //third instance
             Student student3 = new Student();
             student3.Name = "Student Three";
             student3.Address = "678, Peachtree Road, Atlanta, GA 30303";
             student3.StudentID = 3;

             //instantiate an array to store these objects.
             Student[] StudentsList = new Student[2];
             StudentsList[0] = student1;
             StudentsList[1] = student2;
             StudentsList[2] = student3;

            //since array is already of type Student, no typecasting is necessary.
            Console.WriteLine(StudentsList[0]);

       }
    }
}

There are several problems with this approach. First, you have to initialize an array and specify its size. Which means you have to know how many objects you are going to store in an array beforehand. Second limitation is that an array must be specific to the type you are going to store, meaning you cannot store two different types of objects in an array. Also, once an array has been initialized to a specific size, you cannot resize it downwards.

Now let's consider the same example using an arraylist.

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
             
            //first instance
             Student student1 = new Student();
             student1.Name = "Student One";
             student1.Address = "123, Peachtree Road, Atlanta, GA 30303";
             student1.StudentID = 1;
            //second instance
             Student student2 = new Student();
             student2.Name = "Student Two";
             student2.Address = "456, Peachtree Road, Atlanta, GA 30303";
             student2.StudentID = 2;
            //third instance
             Student student3 = new Student();
             student3.Name = "Student Three";
             student3.Address = "678, Peachtree Road, Atlanta, GA 30303";
             student3.StudentID = 3;

            //instantiate an arraylist to store these objects.
             ArrayList StudentList = new ArrayList();   
            
            // notice an arraylist isn't of a specifc type.
             StudentList.Add(student1);
             StudentList.Add(student2);
             StudentList.Add(student3);

            //since arraylist is a generic list, you must type cast it first.
            Console.WriteLine((Student)(StudentList[0]));

            //Arraylist allows for inserting an object at a specific position.

             //fourth instance
             Student student4 = new Student();
             student4.Name = "Student Four";
             student4.Address = "890, Peachtree Road, Atlanta, GA 30303";
             student4.StudentID = 4;
             StudentList.Insert(1, student4);

            //You can also remove an object from an array list
             StudentList.Remove(student4); // remove a specific object
            //OR
             StudentList.RemoveAt(2);   //remove whatever is at index 2
     
        }
    }
}

As you can see, an arraylist avoids some of the problems of an array. First, an arraylist doesn't have to be sized and resized. An element can be added or removed from an arraylist.

Note, since an arraylist isn't cast into a specific type during declaration, when reading the content from an arraylist, you must explicitly cast to a specific type, as show in the above code snippet.

An arraylist also allows for inserting an object at any position, including the position where an object may already exist. If you insert an element at a position already occupied by another element, the current element will simply push down.

Since an arraylist isn't of a particular type, you can add elements of reference or value types in an array, even mixing them.

For example you can do the following.

StudentList[0] = student1;
StudentList[1] = 5;
StudentList[2] = "This is a test";
StudentList[3] = student2;

But if you add objects of different types or value types in the same arraylist, you must first inspect the element to determine its type before casting it to the appropriate type. This is not only cumbersome and error prone, it also adds an unnecessary overhead.

To write out the content from the above example, you now have to do the following...

if (StudentList[1].GetType() == typeof(int))
   {
    //do something
   }

This becomes unusable pretty quickly. So, what should you do to get the flexibility of an arraylist without the added overhead? In the next post we will talk about generic collections and how they can aid us in a situation like this.

Friday, February 24, 2012

Structures in .NET

As we discussed in previous post, enumerations and structures are two complex types that are value types. Structures allow you encapsulate certain data elements similar to a class, except that structures are value types while classes are reference types.

Structures are very similar to classes with few differences.
  • Unlike classes, structures cannot inherit from other structures or a class, although they can implement interfaces.
    • Since they cannot inherit from other structures, an structure cannot be a base structure, which means structure members cannot be declared as "Protected".
  • Similar to classes, structures can have constructors, properties, methods etc.
  • Unlike classes, you cannot declare a parameterless constructor in a structure, although you can declare overloaded constructors with parameters. Strucutres always have a default constructor.
  • Unlike classes, you can instantiate an structure without using "new" operator.
Structures are suitable when you want to implement lightweight objects such as a point or color or a rectangle etc. 

Let's see an example in action...

    using System;
    struct StructExample
    {
        private int _width;
        private int _height;
   
        public int Width
        {
            get { return _width;}
            set {_width = value;}
         }

       public int Height
      {
           get { return _height;}
           set {_height = value;}
      }
   }


Let's use this structure

    Using System;
    class TestStructure
    {
       static void Main()
       {
             StructExample example1 = new StructExample();
             example1.Width  =1;
             example2.Height = 3;
             Console.WriteLine(example1.Width + ' ' + example1.Height);
             Console.Read();
        }
    }

As I mentioned previously, you should only use structures for lightweight objects because they are value types and are stored on a stack. Also, since they are not reference type, you are directly dealing with the structure and not with a reference, like you would with a class.

Thank you.








Wednesday, February 22, 2012

Enumerations

Recall my previous post about value types vs. reference types. Just to recap, simple data types such as int, float, double, decimal etc. are value types while complex types such as objects, strings are reference types. There are two exceptions to this concept. Structures and Enumerations. Despite being complex types, Structures and Enumerators are value types and hence they are stored on stack as opposed to heap.

In this post we will discuss enumerations and we will cover structures in next post.

Enumerations
Enumerations allow you to group constants at one place in a name-value pair format and allows you to access the values using strongly typed names. The key difference between an array list or a dictionary object and enumeration is that the arraylist / dictionary is a reference type and hence stored on heap while enumerators are value types and are stored on stack. Use of enumerators also allow you to keep the constants at one place hence being able to easily manage them and makes your code easier to read.

The underlying datatype for an enumeration can only be of an integral type. It can be of any integral type except "Char". The default type is int.

An enumeration is declared using enum keyword. Lets see an example.

enum Color
{
   Red,
   Blue,
   Green,
   Orange
}

If you don't specify the value, underlying integer datatype is assumed and the value is assigned from 0 onwards. For example in above example, Red=0, Blue=1, Green=2, Orange=3.

You can explicitly assign any value to each type, for example

enum Color
{
   Red = 8,
   Blue = 9,
   Green  =12,
   Orange=20
}


As I mentioned previously, underlying datatype for an enum can be any integral type except char. Following datatypes are supported 
  • byte, sbyte, short, ushort, int, uint, long or ulong.
To use any other datatype except int, declare it as follows...


enum Color : byte
{
   Red ,
   Blue ,
   Green ,
   Orange
}

Usage
Apart from keeping the constants at one place, it also makes code easier to read. See the following example...

 public class EnumTest
 {
   static void Main()
   {
      Console.WriteLine("Red={0}", Color.Red);
      Console.WriteLine("Blue={0}", Color.Blue);
   }
}

That's all there is to it. It is a relatively simple concept but when used appropriately promotes cleaner and readable code.

Thank you.

Monday, February 20, 2012

Reflection in .NET

Reflection is the process of discovering classes, modules, assemblies or the type information of an object at run-time. Reflection works by extracting metadata information from an assembly and using this metadata to do something with it. System.Reflection namespace in .NET Framework provides the classes and interfaces that you can use to discover a class, instantiate it, discover its methods, properties and invoke them at run-time just like you would during compile time.


There are many uses of reflection, but let's demonstrate one potential use with an example.


Suppose for example, you have a sales application installed on sales associates laptops. This application allows sales associates to enter sales orders on their laptops, when they visit the clients. The application is run in offline mode but when the sales associate returns back to the office and connects to the network, the application will detect it and automatically uploads the sales orders in a centrally hosted database.


When a sales associate enters the information, a collection of the Orders object is serialized on sales associates laptop. When this laptop is connected to the company network, the application deserializes the Orders, uses reflection to type cast the object into the Orders Type and then calls the appropriate methods to save data in the database.


Let's illustrate this with an example.

//Create an Orders Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ReflectionTest    
{
public class Orders
{
      private int _itemNumber;      
      private int _quantity;      
      private int _customerNumber;
      //properties
     
      public int ItemNumber
      { 
        get { return _itemNumber; }          
        set { _itemNumber = value; }      
      }
      public int Quantity          
      {
         get { return _quantity; }         
         set { _quantity = value; }      
      }
      public int CustomerNumber         
      {
         get { return _customerNumber; }         
         set { _customerNumber = value; }        
      }
      //constructor
     
      public Orders() 
      {}
     //Method to save data to the database
     
public void SaveToDB(List<Orders> orders)           
     {
       // do something here         
     }
  }
}

 Since we are going to serialize this object and save it on associate's laptop, let's write a class that is serializable and has a variable which stores the collection of Orders object (you can make it generic to allow for serializing and storing any object).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace  ReflectionTest 
{
    [
Serializable]    

    public class SaveObjectLocally    
    {
     //use generics so this class can be used to store any object types not just Orders
    private List<Orders> _collObjects = new List<Orders>();     

    private string _saveMethod;     
    private string _className;
    public SaveObjectLocally() { }     
    //properties
     public List<Orders> ObjectList
     {          
         get { return _collObjects; } 
         set { _collObjects = value; }     
     }
     public string SaveToDB
     {          
         get { return _saveMethod; }          
         set { _saveMethod = value; }     
     }
     public string ClassName          
     {
         get { return _className; }          
         set { _className = value; }     
     }
     //serialize
     public void Serialize(string filePath)
     {
         
Stream stream = File.Open(filePath, FileMode.Create);           

          BinaryFormatter bf = new BinaryFormatter();
          bf.Serialize(stream, this);
          stream.Close();     
     }
    //deserialize
      public SaveObjectLocally DeSerialize(string filePath)         
     {
        Stream stream = File.Open(filePath, FileMode.Open);         
        BinaryFormatter bf = new BinaryFormatter();         
        SaveObjectLocally SaveObject = (SaveObjectLocally)bf.Deserialize(stream);
        stream.Close();  
        return SaveObject; 
          }
 
    }
}

//Main Program

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace  ReflectionTest 
{
    class Program 

    {
        
static void Main(string[] args) 
         {
              
Orders clientOrder = new Orders();
              clientOrder.ItemNumber=123;
              clientOrder.Quantity = 5;
              clientOrder.CustomerNumber=101;
              //lets assign this order to SaveObjectLocally and 

              //then save it on local machine           
             //create a list object
             
List<Orders> ordersList= new List<Orders>();
             ordersList.Add(clientOrder);
             SaveObjectLocally save = new SaveObjectLocally(); 
             save.SaveToDB = 
"SaveToDB"; 
             save.ObjectList = ordersList;


             //serialize

             save.Serialize(@"C:\Temp\Orders.xml");
                
           }
         //deserialize the saved object and upload.
         public static void UploadData() 
          {

          SaveObjectLocally save = new SaveObjectLocally(); 
          SaveObjectLocally retrieveObject = save.DeSerialize(@"C:\Temp\Orders.xml"); 
          string saveMethod = retrieveObject.SaveToDB;
          string className = retrieveObject.ClassName; 
          List<Orders> orders = retrieveObject.ObjectList;
          //now use reflection to instantiate the object
          Type ClassType = Type.GetType(className);          
          object obj = Activator.CreateInstance(ClassType);
          System.Reflection.MethodInfo callingMethod = ClassType.GetMethod(saveMethod);
          callingMethod.Invoke(obj,new Object[] {orders});
         }
         //If you have multiple objects serialized 

        //you can loop through all the files and upload one by one.
   }  
}

The example above is one use of Reflection where you can instantiate an object at run time and invoke its methods.

GetType.GetMethod and GetType.GetMethods() return you a single method or a list of methods.

Similarly, GetType.GetField() and GetType.GetFields() return you a single field or an array of all fields.

GetType.GetProperty() and GetType.GetProperties() returns property or a list of properties respectively.

You can also find out the parameters a method needs and also its return type. MethodInfo() provides information about the return type of a method and GetParameters() provides information about the parameters that a method expects.

GetConstructors() returns a list of constructors associated with this class.

Assembly Class
Assembly class is used to gather information about an assembly and manipulate the assembly. You can use it to load modules and assemblies at runtime and also search the type information within an assembly once it is loaded. Assembly class has the following methods


  • Load() - You can pass the assembly name as input parameter to search and load the assembly.
  • LoadFrom() - Takes the complete path of an assembly to search at a particular location.
  • GetExecutingAssembly() - Get the information about the currently running assembly.
  • GetTypes() - Allows you to obtain the details of all the types that are present in the assembly.
  • GetCustomAttributes() - Gets the list of custom attributes associated with this assembly. You can also pass a Type Object as a second parameter to this method to find the attributes of a specific type associated with this assembly.

As you can imagine, reflection is a very powerful feature that allows for late binding and flexibility otherwise not available during compile time. Hopefully this article will provide you enough pointers to try out reflection on your own and discover some of its additional powerful features.

Thank you and as always, your comments are welcome.

          

Saturday, February 18, 2012

Shallow Vs. Deep Copy


Although the concept is relatively simple, I have seen many developers struggle with the concept of shallow vs. deep copy.

First, both shallow and deep copy involves copying an object to another object. The difference lies in what is copied when the object contains a variable of reference type such as an instance of another object or an array / arraylist.

Shallow Copy
When you copy an object into another object, all the non-static members are copied from the original object to its copy. All the variables of value type are copied, but if the object contains variables of reference type, then only the reference is copied but the actual referred object is not copied. So, both the actual object and its copy refer the same instance of the object that is being referenced.

For example, consider the following class, which references another object

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace ShallowDeep
{
[Serializable]
public class Employee
{
    private string _name;
    private int _age;
    private Address _empAddress; // reference to another class, hence a reference type.
    public String Name
     {
        get { return _name; }
        set { _name = value; }
     }
    public int Age
     {
        get { return _age; }
        set { _age = value; }
     }
    public Address EmpAddress
     {
        get { return _empAddress; }
        set { _empAddress = value; }
     }
    //method to create a shallow copy
    public Employee CopyShallow(Employee EmpCopy)
       {
         //use MemberWiseClone to create a shallow copy
         return (Employee)EmpCopy.MemberwiseClone();
       }
    //Method to clear a deep copy
    public Employee CopyDeep(Employee EmpDeepCopy)
       {
          MemoryStream ms = new MemoryStream();
          BinaryFormatter bf = new BinaryFormatter();
          bf.Serialize(ms, EmpDeepCopy);
          ms.Seek(0, SeekOrigin.Begin);
          Employee result = (Employee)bf.Deserialize(ms);
          ms.Close();
          return result;
       }
   }
 
 }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ShallowDeep
{
    public class Address
    {
        private String _mailingAddress;

        //constructor
        public Address(string MailingAddress)
        {
           _mailingAddress = MailingAddress;
        }
        public String EmpAddress
        {
            get{return _mailingAddress ;}
            set{ _mailingAddress =value;}
        }
     }
 }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ShallowDeep
{
class Program
{
    static void Main(string[] args)
    {
       //Shallow Copy
       //create an instance of Employee Class
       Employee oEmployee = new Employee();
       oEmployee.Name="Test User";
       oEmployee.Age = 30;
       Address oAddress = new Address("123 Ross Street, Atlanta, GA, 12345");
       oEmployee.EmpAddress=oAddress;
       //Now perform a shallow copy
       Employee oEmployee2 = oEmployee.CopyShallow(oEmployee);
      //Now lets do the following
      oEmployee2.Age = 25;
      oAddress.EmpAddress = "303 Peachtree Road, Atlanta, GA, 30032";
      //Check the value of oEmployee2.EmpAddress.
     int empOriginalAge = oEmployee.Age;
     int empCopyAge = oEmployee2.Age;
     Address EmpOriginalAddr = oEmployee.EmpAddress;
     Address EmpCopyAddr = oEmployee2.EmpAddress;
   }
  }
}


Notice the value of empOriginalAge=30 but the value of empCopyAge=25, but the value of EmpOriginalAddr and EmpCopyAddre is same i.e. "303 Peachtree Road, Atlanta, GA, 30032"


Deep Copy
To be able to deep copy an object, it must be serializable. Difference between a shallow and deep copy is that in addition to a bit by bit copy of a value object, deep copy also copies the reference object, instead of just copying only the reference to the object.

Let's use the same example as above, but instead use DeepCopy method.

Add the follow snippet to the method above.
//Deep Copy
//create an instance of Employee Class
Employee oEmployeeDeep = new Employee();
oEmployeeDeep.Name="Test User";
oEmployeeDeep.Age = 30;
Address oAddress2 = new Address("123 Ross Street, Atlanta, GA, 12345");
oEmployeeDeep.EmpAddress=oAddress2;
//Now perform a deep copy
Employee oEmployeeDeep2 = oEmployee.CopyDeep(oEmployeeDeep);
oEmployeeDeep2.Age = 25;
oAddress2.EmpAddress = "303 Peachtree Road, Atlanta, GA, 30032";
//Check the value of oEmployee2.EmpAddress.
Address EmpAddress = oEmployeeDeep2.EmpAddress;



The value of the EmpAddress will still be "123 Ross Street, Atlanta, GA, 12345".

Hope this helps clarify the difference between a shallow and deep copy. Remember, shallow sopy is done via MemberWiseClone(), while a deep copy is performed by serializing the object, hence the class must be serializable.

Just remember, the key difference is that in shallow copy only a reference to any reference type variable  is copied while in deep copy, the referenced object itself is copied.

Thank you and as always, your comments are appreciated.