Object Creation


Object creation in C# is typically no different in code from how it is done for a variety of other languages. C++, Java, and VB developers have always used the new keyword to create a new object on the heap (C++ developers can use malloc(), heapalloc(), and so on, but these functions don't implicitly call the object constructor). Generally, all fields within an object are either assigned a value at creation time or are given an implicit value by the runtime if no assignment takes place (this is not the case with C++, which will generate both warnings and exceptions if there are no default values set). In C#, default assigned values depend on whether the field is a reference to a value type or a reference type. A reference type would by default initialize to null if no value was assigned to it. A value type such as int would initialize to 0 by default. The System.ValueType class (from which value types inherit) has a default constructor, which is invoked by the derived value type class (such as an int) and initializes the state for the class instance. Remember that System.String is not a value type and so it does not initialize to the empty string on construction.

The Employee class opposite demonstrates the issues involved with creating an object and initializing values. The field value is only assigned to the dept field; the others will be assigned default values, null for the string and 0 for the int. It is good practice to expose these private fields as property values as shown in the code. The following code file is called object_creation.cs:

     using System;     class Employee     {       private string name;       private string dept = "IT";       private int salary;       public string Name { get {return name;} }       public string Dept { get {return dept;} }       public int Salary { get {return salary;} }     }     public class emp_class     {       static void Main(string[] args)       {         Employee emp = new Employee();         Console.WriteLine("Name: {0}\nDept: {1}\nSalary: {2}",                           emp.Name, emp.Dept, emp.Salary);       }     } 

The above code will issue a warning stating that the Employee.name and Employee.salary fields are never assigned and are given default values of null and 0 respectively. On running the program the following output is seen:

     C:\Class Design\Ch 05>object_creation     Name:     Dept: IT     Salary: 0 

This idea of assigning default values to the fields helps us to avoid exceptions that can continually occur in code because the default values are outside the acceptable boundary values for application languages such as Java and VB, which will also compile without default assignments and generate null reference exceptions (or in the case of VB – Object variable or with block not set) if the fields are used without an additional assignment. It is always good practice to initialize field values irrespective of the default assignment since values assigned by the runtime may not conform to acceptable boundary values if the code fails to assign them at a later stage and uses them.

An important point here is that a class's field values are generally not known at design time and they may need to be initialized by the code that creates the class. For this reason C#, like virtually all other object-oriented languages, provides the ability to define class constructors. If this constructor exists, then it will be invoked when the object creation code uses the new keyword to create the object, the invocation of the constructor will then be part of the initialization process. C# supports that concept of overloading constructors which we will assess later in the chapter. The constructor is extremely important for initializing fields with values at run time – this is part of the object creation process so before a reference to the object is returned to the client code default field values can be set. Unlike a regular method, the constructor cannot be called explicitly; it will be called if it exists when the object is created and cannot have a return type. Every time we create an object, a constructor is called implicitly to initialize the state of the object.

In order to address some of the issues with initialization, we can create constructors with different signatures, that contain different lists and types of parameters, and only one of these will be called when the object is created (unless the others are called internally – this is a common practice, which we will review later in the chapter). The Employee class will need different types of constructor for different reasons. For example, we may need to populate all three fields when the object is created or we may only need to populate two fields since the default dept value is IT and the Employee we are creating belongs to the IT department. Additionally, we may not need to populate any of the object's field values, which could entail a single constructor without any parameters and provide some other form of initialization that doesn't involve the fields – this type of constructor may be useful when the object is responsible for its own field values that are initialized using other techniques, such as the combination of attributes and serialization. The code snippet shown below is constructor_parameters.cs:

     public class Employee     {       public Employee()       {         Console.WriteLine("Default constructor called with no params");       }       public Employee(string name, string dept, int salary)       {         this.name = name;         this.dept = dept;         this.salary = salary;         Console.WriteLine("Constructor called with three params");       }       public Employee(string name, int salary)       {         this.name = name;         this.salary = salary;         Console.WriteLine("Constructor called with two params");       }     } 

We now need to add a Main() method. In the following example, the three Employee objects are created to take advantage of the new constructors. If we use breakpoints in Visual Studio .NET to check the order of execution, we will find that the fields are initialized (specifically the dept field) before the constructor is called. In this way we can always override the default field values using the constructor to allow us to specify default field values at design time and the final values at run time before a class instance is returned.

     public class TestEmployee     {       static void Main(string[] args)       {         Employee emp1 = new Employee();         Console.WriteLine("Name: {0}\nDept: {1}\nSalary: {2}",                            emp1.Name, emp1.Dept, emp1.Salary);         Console.WriteLine("----------------------");         Employee emp2 = new Employee("Jones", "Operations", 30000);         Console.WriteLine("Name: {0}\nDept: {1}\nSalary: {2}",                            emp2.Name, emp2.Dept, emp2.Salary);         Console.WriteLine("----------------------");         Employee emp3 = new Employee("Smith", 35000);         Console.WriteLine("Name: {0}\nDept: {1}\nSalary: {2}",                            emp3.Name, emp3.Dept, emp3.Salary);       }     } 

The output from this is shown below and matches our expectations. Calling the default constructor has not changed the initialization values of the fields:

     C:\Class Design\Ch 05>emp_constructors     Default Constructor     Name:     Dept: IT     Salary: 0     ----------------------     Constructor called with three params     Name: Jones     Dept: Operations     Salary: 30000     ----------------------     Constructor called with two params     Name: Smith     Dept: IT     Salary: 35000 




C# Class Design Handbook(c) Coding Effective Classes
C# Class Design Handbook: Coding Effective Classes
ISBN: 1590592573
EAN: 2147483647
Year: N/A
Pages: 90

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net