Instantiating Objects from Classes

Instantiating Objects from Classes

After you obtain a reference to an object and assign it to a variable, you can manipulate the object using an object variable. Let's do so now.

Click the frmClassExample.cs Design tab to view the Form Designer and add a button to the form by double-clicking the Button item in the toolbox. Set the button's properties as follows:










Create Object

Next, double-click the button to access its Click event and enter the following code:

clsMyClass objMyObject = new clsMyClass();

The first statement creates a variable of type clsMyClass. (Declaring variables was discussed in Hour 11, "Using Constants, Data Types, Variables, and Arrays.") The new keyword tells Visual C# to create a new object, and the text following new is the name of the class to use to derive the object (remember, classes are object templates). So, this first step creates a variable holding a reference to a new object based on clsMyClass. The last statement calls the AddTwoNumbers() method of your class and displays the result in a message box after converting the return value to a string.

Go ahead and run the project by pressing F5 and then click the button to make sure that everything is working correctly. When finished, stop the project and save your work.

Binding an Object Reference to a Variable

An object can contain any number of properties, methods, and events; every object is different. When you write code to manipulate an object, Visual C# has to understand the interface of the object, or your code won't work. Resolving the interface members (the properties, methods, and events of the object) occurs when an object variable is bound to an object. There are two forms of binding: early binding (which occurs at compile time) and late binding (which occurs at runtime). It's important that you have at least a working understanding of binding if you're to create code based on classes. Although I can't explain the intricacies and technical details of early binding versus late binding in this hour, I'll teach you what you need to know to perform each type of binding.

By the Way

Benefits exist to both types of binding, but early binding is generally superior to late binding because code that uses late-bound objects requires more work by Visual C# than code that uses early-bound objects.

Late Binding an Object Variable

When you dimension a variable as data type Object, as shown in the following code sample, you're late binding to the object:

object obj;
obj = new clsMyClass();
MessageBox.Show(obj.AddTwoNumbers(1, 2).ToString());

When you late bind an object, the binding occurs at runtime when the variable is set to reference an object. For a member of the object to be referenced, Visual C# must determine and use an internal ID of the specified member. Fortunately, because Visual C# handles all the details, you don't need to know the ID of a member. Just be aware that Visual C# does need to know the ID of a member to use it. When you late bind an object variable (dimension the variable As Object), the following occurs behind the scenes:

Visual C# obtains a special ID (the Dispatch ID) of the property, method, or event that you want to call. This takes time and resources.

An internal array containing the parameters of the member, if any, is created.

The member is invoked using the ID obtained in step 1.

The preceding steps require a great deal of overhead and adversely affect the performance of an application. Therefore, late binding isn't the preferred method of binding. Late binding does have some attractive uses, but most of them are related to using objects outside your application, not to using objects derived from classes within the project.

One of the main drawbacks of late binding is the inability of the compiler to check the syntax of the code manipulating an object. Because the ID of a member and the parameters it uses aren't determined until runtime, the compiler has no way of knowing whether you're using a member correctlyor even if the member you're referencing exists. This can result in a runtime exception or some other unexpected behavior.

Early Binding an Object Variable

If Visual C# can determine a Dispatch ID for a member at compile time, there's no need to look up the ID when the member is referenced at runtime. This results in considerably faster calls to object members. Not only that, but Visual C# can also validate the member call at compile time, reducing the chance of errors in your code.

Early binding occurs when you dimension a variable as a specific type of object, rather than just as object. When a variable is early bound, Visual C# looks up the Dispatch IDs of the object's members at compile time, rather than at runtime.

The following are important reasons to use early binding:

  • Speed.

  • More speed.

  • Objects, their properties, and their methods appear in IntelliSense drop-down lists.

  • The compiler can check for syntax and reference errors in your code so that many problems are found at compile time, rather than at runtime.

For early binding to take place, an object variable must be declared as a specific object type (that is, not as object).

Creating a New Object When Dimensioning a Variable

You can instantiate a new object on the declaration statement by including the keyword new, as you did in this example. This approach alleviates the need for a second statement to create a new instance of the object. However, if you do this, the variable will always contain a reference to an object. If a chance exists that you might not need the object, you should probably avoid using the new keyword on the declaration statement. Consider the following:

clsMyClass obj;

if (condition)
   obj = new clsMyClass();
   /// Code to use the custom object would go here.

Remember that instantiating an object takes resources. In this code, no object is created when condition is False. If you were to place the word new on the declarations statement, a new object would be instantiated whenever this code was executed, regardless of the value of condition.

Releasing Object References

When an object is no longer needed, it should be destroyed so that all the resources used by the object can be reclaimed. Objects are destroyed automatically when the last reference to the object is released. Although two primary ways exist to release an object reference, one is clearly better than the other.

One way to release a reference to an object is simply to let the object variable holding the reference go out of scope. As you might recall from Hour 11, variables are destroyed when they go out of scope. This is no less true for object variables. However, you can't necessarily be assured that an object is fully released and that all the memory being used by an object is freed by letting an object's variable go out of scope. Therefore, relying on scope to release objects isn't a good idea.

To explicitly release an object, set the object variable equal to null, like this:

objMyObject = null;

When you set an object variable equal to null, you're assured that the object reference is fully released. Again, just because the reference is released does not mean the object is destroyed! The garbage collector will periodically check for unused objects and reclaim the resources they consume, but this may occur a considerable length of time after the object is no longer used. Therefore, you should add a Dispose() method to all your classes. You should place cleanup code within your Dispose() method and always call Dispose() when you are finished with an object. One thing to keep in mind is that it's technically possible to have more than one variable referencing an object. When this occurs, calling Dispose() may cause cleanup code to execute and therefore cause problems for the code using the second object variable. As you can see, you need to consider many things when programming objects.

If you don't correctly release object references, your application might experience resource leaks, become sluggish, and consume more resources than it should.

Understanding the Lifetime of an Object

An object created from a class exists as long as a variable holds a reference to it. Fortunately, Visual C# (or more specifically, the .NET Framework as discussed in Hour 24) handles the details of keeping track of the references to a given object; you don't have to worry about this when creating or using objects. When all the references to an object are released, the object is flagged and eventually destroyed by the garbage collector.

The following are key points to remember about an object's lifetime, and what they mean to your application:

  • An object is created (and hence referenced) when an object variable is declared using the keyword new. For example:

    clsMyClass objMyObject = new clsMyClass();
  • An object is created (and hence referenced) when an object variable is assigned an object using the keyword new. For example:

    objMyObject = new clsMyClass();
  • An object is referenced when an object variable is assigned an existing object. For example:

    objThisObject = objThatObject;
  • An object reference is released when an object variable is set to null (see the section "Releasing Object References" earlier in this hour).

  • An object becomes eligible for garbage collection after the last reference to it is released. Many factors, including available system resources, determine when the garbage collector executes next and destroys unused objects (please see Hour 24 for more information on the garbage collector).

Understanding the lifetime of objects is important. You've now seen how and when object references are created, but you also need to know how to explicitly release an object reference. Only when all references to an object are released is the object flagged for destruction and the resources it uses reclaimed.

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows