Vous êtes sur la page 1sur 57

A Twisted Look at Object Oriented Programming in C# - Introduction

AuthorJeff Louie

Introduction
I must admit that my first exposure to object oriented programming (OOP) was frustrating and difficult. As a hobbyist I have struggled through Z80 assembly and EPROM burners, BASIC, Turbo Pascal, Java, C++ COM and now C#. The move to event driven programming and then to object oriented programming presented major conceptual hurdles to my function driven sequential programming mindset. The aha moment when OOP made sense was most gratifying, but did not come quickly or easily. It has been a few years since I got the OOP mindset and I feel comfortable enough now to try to help fellow travelers with this journey. If OOP comes easily to you, feel free to skip this tutorial. If you are having problems getting your mind around objects and inheritance I hope this tutorial can help you. This tutorial does not represent a conventional teaching method. It assumes a passing knowledge of the C# language and familiarity with the Visual Studio .NET IDE. This is a work in progress and may require correction or revisions.

Classes, Objects, and Properties


Why program with objects and inheritance? Simply put, programming with objects simplifies the task of creating and maintaining complex applications. OOP is a completely different way of thinking that differs significantly from the more traditional function driven sequential programming model of old. Programming with objects without inheritance is object-based programming. Adding inheritance to objects is object-oriented programming. OOP provides built in support for code reuse (inheritance) and support for runtime variations in program behavior (polymorphism). Without attempting to define these terms, OOP at a minimum: 1. 2. 3. Simplifies the creation and maintenance of complex applications. Promotes code reuse. Allows flexibility in runtime program behavior (a very cool feature).

What is OOP? Well, lets cut right to the point. What the heck is Object Oriented Programming? Answer: It is a whole new way of thinking about programming! It is a way of modeling software that maps your code to the real world. Instead of creating programs with global data and modular functions, you create programs with classes. A class is a software construct that maps to real world things and ideas. Think of a class as a blueprint that contains information to construct a software object in memory. Unlike a simple data structure, software objects contain code for both data and methods. The class binds the data and methods together into a single namespace so that the data and methods are intertwined. Just as you can build more than one house from a single blueprint, you can construct multiple software objects from a single class. Each object (represented by code in memory) is generated from a class and is considered an instance of the class. Since each instance of the class exist in separate memory space, each instance of the class can have its own data values (state). Just as multiple houses built from a single blueprint can differ in properties (e.g. color) and have identity (a street address), multiple objects built from a single class can differ in data values and have a unique identifier (a C++ pointer or a reference handle in C#). Got that! Now take and break and re-read this paragraph. When you come back, you can look at some C# code. What is a class?

A class is a software construct, a blueprint that can describe both values and behavior. It contains the information needed to create working code in memory. When you create an object, you use the information in the class to generate working code. Lets create a simple program that models a toaster! The toaster is a real life object. The toaster can have state such as secondsToToast and has a behavior, MakeToast(). Here is our first toaster class in C#:

class Toaster1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // Toaster1 t= new Toaster1(); System.Console.WriteLine(t.MakeToast()); System.Console.ReadLine(); } private int secondsToToast= 10; public string MakeToast() { return "Toasted for "+secondsToToast.ToString()+" seconds."; } }
If you execute this program, the output is:

Toasted for 10 seconds.


A working toaster yes, but not very useful unless you like 10-second toast <g>. What is an object? An object is an instance of a class. A specific class describes how to create a specific object in memory. So the class must contain information about the values and behaviors that each object will implement. You can create an object using the reserved word new. In our Toaster1 application, you create a single instance of the Toaster1 class with the call:

Toaster1 t= new Toaster1();


The reference variable t, now contains a reference to a unique instance of the Toaster1 class. You use this reference variable to touch the object. In fact, if you set the reference variable t to null, so that the object is no longer touchable, the garbage collector will eventually delete the Toaster1 object!

t= null; // If "t" contains the only reference to the Toaster1 object, the object can be garbage collected. (Strictly speaking, if the Toaster1 object cannot be "reached", it can be garbage collected.)
MakeToast() is a public method of the Toaster1 object so it can be called from outside the class (Main) using the reference variable t to touch the objects behavior:

t.MakeToast();
Since each object exists in a separate memory space, each object can have state, behavior and identity. Our Toaster1 object has identity since it is unique from any other object created from the Toaster1 class:

Toaster1 t2= new Toaster1();


Now there are two instances of the Toaster1 class. There are two reference variables t and t2. Each reference variable identifies a unique object that exists in a separate memory address. Since each object contains a method MakeToast(), each object has behavior. Finally, each object contains a value secondsToToast(). In a sense, each object now has its own state. However, the state is the same for each object! This is not a very useful class design. In fact, the Toaster1 class is not a good representation of a real world toaster since the toast time is immutable. Here is a second run at the Toaster class that demonstrates the use of public accessors, get and set methods. This is a standard idiom in OOP. The actual data is declared private (or protected) so that users of the class cannot access the underlying data. Instead, public methods are exposed to the callers of the class to set and get the underlying hidden data values. Note: The modifiers private, protected and public are access modifiers that control the visibility of methods and data. The compiler will enforce these visibility rules and complain if you say try to touch a private variable from outside the class. Public methods and data are visible to any caller. Private methods and data are only visible and touchable within the class. Protected is a special level of access control of great interest to object oriented programmers, but is a subject that must be deferred to the chapter on inheritance. If you dont declare an access modifier, the method or variable is considered private by default.

using System; namespace JAL { /// <summary> /// Summary description for class. /// </summary> /// class Toaster2 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { Toaster2 t= new Toaster2(); t.SetSecondsToToast(12); Console.WriteLine(t.MakeToast()); Console.ReadLine(); } private int secondsToToast= 0; public string MakeToast() { return "Toasted for "+GetSecondsToToast().ToString()+" seconds."; } // Public Accessor Functions, Get and Set

public bool SetSecondsToToast(int seconds) { if (seconds > 0) { secondsToToast= seconds; return true; } else { secondsToToast= 0; return false; } } public int GetSecondsToToast() { return secondsToToast; } } }
The callers of the class cannot touch the secondsToToast variable which remains private or hidden from the caller. This idiom is often called encapsulation so that the class encapsulates or hides the underlying data representation. This is an important aspect of OOP that allows the writer of the class to change the underlying data representation from say several variables of type int to an array of ints without affecting the caller. The class is a black box that hides the underlying data representation. In this new version of toaster, Toaster2, there are two new methods: SetSecondsToToast() and GetSecondsToToast(). If you look at the setter method it validates the callers input and sets the value to zero if the callers input is invalid (<0):

public void SetSecondsToToast(int seconds) { if (seconds > 0) { secondsToToast= seconds; } else { secondsToToast= 0; } }
The getter method really does not do much simply returning the private data value secondsToToast:

public int GetSecondsToToast() { return secondsToToast; }


What is a property? C#.NET implements a language idiom called a property. In a nutshell, a property is a method that appears as a variable. By convention, a property name starts with an uppercase letter. Here is our new version of Toaster that replaces the get and set methods with properties:

using System; namespace JAL { /// <summary> /// Summary description for class. /// </summary> /// class Toaster3 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { Toaster3 t= new Toaster3(); t.SecondsToToast= 12; // the property idiom Console.WriteLine(t.MakeToast()); Console.ReadLine(); } private int secondsToToast= 0; public string MakeToast() { return "Toasted for "+secondsToToast.ToString()+" seconds."; } // Properties public int SecondsToToast { get {return secondsToToast;} set { if (value > 0) { secondsToToast= value; } else { secondsToToast= 0; } } } } }
Here are the new setter and getter methods as properties:

// Properties public int SecondsToToast { get {return secondsToToast;} set { if (value > 0) { secondsToToast= value; } else { secondsToToast= 0; }

} }
The reserved word value is used to represent the callers input. Note the syntax used to call a property. To set a property use:

t.SecondsToToast= 12;
The method set() now appears as a variable SecondsToToast. So a property is a method that appears as a variable. Well, congratulations. You have constructed your first real world class in C#. Since this is a hands on tutorial, I strongly urge you to compile the Toaster3 code and experiment.

Where is My Inheritance?
In this chapter you will learn how the fictional character Phaedrus explains the complex subject of a class hierarchy in "Zen and the Art of Motorcycle Maintenance", Robert M. Pirsig, Quill, 1974, 418 pp. You will also learn the art of "black box programming" with abstract classes and abstract methods. Lets Get Abstract One of the major advantages of OOP is that is simplifies the task of creating and maintaining complex applications. The road to this simple life is through "abstraction". Abstraction is the ability to "decompose" a complex problem or structure into simpler problems or pieces. In abstraction, you try to find the "essence" of a thing or idea. You break down a complex problem into smaller, more manageable chunks. Abstraction is what the character Phaedrus describes in Chapter 8 in "Zen and the Art of Motorcycle Maintenance." "John looks at the motorcycle and he sees steel in various shapes and has negative feelings about theses steel shapes and turns off the whole thing. I look at the shapes of the steel now and I see ideas. He thinks I am working on parts. I'm working on concepts." Phaedrus then proceeds to divide up the concept of a motorcycle into components and functions. Then he divides the components into a power assembly and a running assembly. To which he concludes: "Finally you see that while I was splitting the cycle up into finer and finer pieces, I was also building a structure. This structure of concepts is formally called a hierarchy and since ancient times has been a basic structure for all Western knowledge.... That's all the motorcycle is, a system of concepts worked out in steel." Thus the fine art of motorcycle maintenance is based on abstraction, decomposing the complex concept of the motorcycle into a hierarchy of smaller simpler concepts. The fine art of OOP is also based on abstraction. You decompose the complex application domain into a hierarchy of smaller pieces that make the application easier to create and maintain. Now I am not saying that Phaedrus was a great object oriented programmer, but he clearly understood the importance of critically examining the problem at hand and dividing up the problem into a hierarchy of ideas. Let's look at Phaedrus' motorcycle in C#. First, a motorcycle is a vehicle since it can carry a payload. Second, it is motorized since it has a motor and consumes fuel. The "essence" of a motorcycle is that of a "vehicle" that is "motorized". Of course a motorcycle differs from a a car, an airplane, or a boat. Motorized vehicles can be ridden, driven, flown or piloted. Land vehicles

can have two wheels or four wheels. What we have here is a hierarchy of ideas. We go from a most general concept to a more specific or "specialized" concept. Just as Phaedrus' abstraction of the motorcycle made him a better mechanic, your abstraction of a complex application, makes you a better and more efficient programmer. You do not think of a program as concrete parts (global data and methods). You think of a program as a hierarchy of ideas. Welcome to "Zen and the Art of Application Maintenance." Inheritance Is the Means to Abstraction Let's face it. Just creating a hierarchy of ideas is not enough. The language must provide a mechanism to support the abstraction hierarchy. That mechanism is called inheritance. Inheritance allows programmers to modify or extend (or inherit) the properties and behavior (methods) of a class. It promotes "code reuse", the holy grail of programming. Throughout the .NET framework, you see the use of abstraction and class hierarchies. Inheritance in the .NET Framework All classes in the .NET framework derive from a single base class called Object. The Object class is the "root of the type hierarchy." Even the built in value types are aliases to classes that derive from Object, so that int actually maps to System.Int32, which derives from Object. As a result, you can call the Object class methods Equals, Finalize, GetHashCode and ToString on any class in the .NET framework. This makes it very easy to debug an application using console output since any .NET class will implement the ToString() method. An example of inheritance in the ASP.NET framework is a TextBox. Here is the class hierarchy for System.Web.UI.WebControls.TextBox:

System.Object System.Web.UI.Control System.Web.UI.WebControls.WebControl System.Web.UI.WebControls.TextBox


The TextBox control inherits from WebControl which inherits from Control which inherits from Object. Wow. And I thought my family tree was complicated. Getting Your Inheritance In the following section you, a twisted programmer, build a "SpaceToaster" class in C# that inherits from the Toaster class. Disclaimer: This is a very twisted tutorial. Reading this online book may be hazardous to your mental health. You have been contracted by a famous "Boy Genius" movie cartoon character to extend the common household toaster for use as a orbiting satellite transmitter. SpaceToaster is a specialization of a Toaster that extends the behavior of the lowly toaster into a satellite. Note: For those of you who don't know what cartoon movie I am talking about, either you have no children or you need to get out more. Here's a hint: "Jimmy Neutron Boy Genius", Paramount Movies, Nickelodeon Movies, 2001. First you need to delete the Main method of the Toaster3 class since an executable can only have one entry point. You can now create a new class "SpaceToaster" that inherits all of the code in the Toaster3 class and has a Main method:

class SpaceToaster : Toaster3 { [STAThread] static void Main(string[] args) { } }


This is not a very useful class! The syntax for inheritance is

class ChildClass : ParentClass {}


Note: Toaster3 is the parent class and SpaceToaster is the child class. You could also say the the child class is a "subclass" or "derived class" and that the parent class is the "superclass" or "base class." The child inherits the knowledge (methods and variables) of the parent class, but can only "touch" the public (and protected) methods and variables of the parent. Sort of reminds me of a trust account. The child's ability to "touch" the assets of the trust is limited. Next, you can add a new behavior to the derived class extending the functionality of the lowly Toaster:

class SpaceToaster : Toaster3 { [STAThread] static void Main(string[] args) { SpaceToaster st= new SpaceToaster(); Console.WriteLine(st.Broadcast()); Console.ReadLine(); } public string Broadcast() // <-- new behavior { return "Hello From Earth!"; } }
Which amazingly outputs: "Hello From Earth!" Since SpaceToaster also inherits the methods and properties of Toaster3, it can still make toast while orbiting planet Earth:

class SpaceToaster : Toaster3 { [STAThread] static void Main(string[] args) { SpaceToaster st= new SpaceToaster(); Console.WriteLine(st.Broadcast()); st.SecondsToToast= 10; Console.WriteLine(st.MakeToast()); Console.ReadLine(); } public string Broadcast() { return "Hello From Earth!";

Inheritance vs. Containment One difficult design decision is to decide if a class should inherit from a parent class or hold a reference to a new object. Inheritance represents an IS_A relationship from a generalization to a specialization. Containment represents a HAS_A relationship between the whole and a part. So a car IS_A motorized vehicle, but HAS_A radio. The two relationships can be expressed in code thusly:

class Radio { ... } class Vehicle { ... } class Car : Vehicle { Radio r= new Radio(); }
The essence of a car is that it is a vehicle. A radio is not essential to a car. Instead a radio is part of a car. That said; let me acknowledge that none of my teenage children agree with me. They are adamant that a radio with a CD player _is_ essential to a car. So a teenage design looks more like:

class TeenageVehicle : Radio { ... }


Public, Protected and Private Heck. I forgot that I had promised in Chapter 1 to explain the access modifier "protected". In a nutshell, a private method or variable is only touchable within the class that declared the variable. A public method or variable is touchable from outside the class. A protected method or variable lies between public and private. Protected methods or variables are only touchable (visible) from within the declaring class _or_ from a class that inherits from the declaring class. So declaring a variable protected allows a designer to access your base class variable inside of their derived class. Suffice it to say that there has been a lot of discussion about the use of private versus protected in class design. Make It Abstract Is your head spinning yet? If so, I apologize, but I need to introduce one more subject that is related to abstraction, the "abstract class". An abstract class defines zero or more abstract methods. An abstract method defines the signature of the method, but not the body of the method. You cannot create an instance of an abstract class. Note: Similar in concept to an abstract class is the concept of an "interface". However, an interface contains no implementation, only abstract methods, and is similar to a pure virtual class in C++.

Nothing helps explain a new programming idiom like sample code. Here is an abstract C# class "SpaceToaster" that defines an empty abstract method "BroadcastID()":

abstract class SpaceToaster : Toaster3 { public string Broadcast() { return "Hello From Earth!"; } abstract public string BroadcastID(); // <-- No body or implementation! }
If you try to create an instance of this abstract class, the compiler will complain:

Cannot create an instance of the abstract class or interface 'JAL.SpaceToaster'


An abstract class is useful in at least four distinct situations. Defer the Implementation to Another More Knowledgeable Class First, an abstract class is useful when you know what the class should do, but you don't know how to implement the total solution. In this idiom, you defer the actual implementation or body of one or more methods to another class. A good example of deferred implementation is a sorting class, say a quicksort. You may know how to do a quicksort, but you cannot know the ordinality or ranking of every possible object that needs to be sorted. You may want to write a complex generic sort routine and declare the class abstract with an abstract method Compare(object1, object2). You can even call this abstract Compare method in your Sort class (cool!). Now another programmer with a custom object that needs to be sorted, can inherit from your Sort class and implement the Compare method with code that defines the ordinality of the custom object, reusing your generic quicksort algorithm! In a sense, the child class inherits the incomplete implementation of your Sort class. Note: C# supports single inheritance of implementation and multiple inheritance of interfaces. In C#, see the IComparable interface. Formally Hide or Encapsulate the Implementation for Flexibility Alternatively, you may just want to formally hide or encapsulate the actual implementation of a method. By requiring clients to program to the public view, the abstract method, rather then to the actual implementation, you promote information hiding or encapsulation. This allows you to change the implementation in a future release, without affecting any client calls. The key concept here is that the implementation can change without affecting a call to your abstract method. This is yet another example of how OOP makes it easier to maintain your code. If you define an abstract method GetData(), the data could come from a database query. To the caller of the abstract method, GetData() is just a black box that returns data. If you later decide to change the concrete implementation of GetData() from a database solution to a text file solution, you can recompile the concrete implementation of GetData() without recompiling classes that call the abstract method GetData(). More interestingly, you could compile an updated class with a different name and load the updated class at runtime (perhaps passing the name of the new class in the Main method). As

long as the updated class derives from the same abstract class and as long as the client makes calls through the abstract class, there is no need to recompile the client application. Cool! Allow Runtime Variation in Implementation This concept is difficult to grasp at first, but is an extremely powerful idiom. In this idiom, one or more concrete classes inherit from an abstract class, but each child class may provide a different implementation of the the abstract class method or methods. The client does not know what concrete class is going to be requested at runtime, but simply invokes the public view of the method. The actual runtime behavior will depend on which concrete classes is requested at runtime. Thus the method can have more than one form at runtime, which is referred to as polymorphism, to have more than one form. The classic example is an abstract class Drawable with an abstract method DrawYourself(). Different concrete classes of Drawable items (such as circle or square) implement the DrawYourself() method in a unique manner and inherit from Drawable. You can now create a Hashtable of non-null Drawable objects and iterate over the collection calling someObjectInHashtable.DrawYourself(). Each concrete object in the collection is guaranteed to implement the DrawYourself() method. Note: Polymorphism implies late binding of a method name to a concrete implementation. In some languages, this magic is done with a v_table, which stores an offset pointer to the actual concrete implementation. OK. That was probably more than you wanted to know. Mark Thyself Finally, the abstract class can simply be a marker, allowing you to identify all classes that are based on your empty abstract class like this:

abstract class MyMarker {} // <-- no abstract methods class Child : MyMarker { static void Main(string[] args) { Child c= new Child(); if (c is MyMarker) { System.Console.WriteLine("Is mine."); } System.Console.ReadLine(); } }
Outputs: "Is mine." Sample C# Code We finish this chapter with a bit of sample code that demonstrates the syntax of inheritance from an abstract class. Here again is the abstract version of the SpaceToaster class:

abstract class SpaceToaster : Toaster3 { public string Broadcast() { return "Hello From Earth!";

} abstract public string BroadcastID(); // <-- No body or implementation! }


This abstract class defines the public outside view or signature of the method "BroadcastID". The method is declared with a return type "string" and an empty parameter list. The declaration says nothing of how the method is implemented. Any concrete class that inherits from this abstract class, must provide a body or implementation for the function BroadcastID(). Here is an concrete version of a class that inherits from the SpaceToaster class and provides an implementation of the abstract method BroadcastID(). Note the use of the keyword "override" which tells the compiler that you are explicitly implementing the abstract method BroadcastID in your concrete class.

class TwistedSpaceToaster : SpaceToaster { [STAThread] static void Main(string[] args) { TwistedSpaceToaster tst= new TwistedSpaceToaster(); Console.WriteLine(tst.BroadcastID()); Console.ReadLine(); } public override string BroadcastID() // <-- concrete implementation { return "Manufactured By Twisted."; } }
Running this code outputs: "Manufactured By Twisted." Congratulations at making it this far. All of this theory, however, is giving me a headache. Lets move on to some real world techniques for writing better programs. In the next twisted chapter, we learn a basic design pattern for writing reusable code, the Model-View/Controller pattern.

Model--View/Controller
Enough theory. It's time to code! In this chapter, you will learn about the most basic design pattern, the Model--View/Controller architecture (M-VC). This lesson contains the complete source code of a Model class that encapsulates the complex math required to do mortgage calculations. You will then create a working Mortgage calculator as a Windows Form application. Finally, you will reuse the Model class to create a working calculator as a Web Form application. This is all working C# code that demonstrates the advantages of using the M-VC design pattern. Model -- View/Controller Architecture A design pattern is a recurring solution that simplifies the design process. The thoughtful study of design patterns allows a developer to learn from the pioneering work of others. The M-VC design pattern is most important, I think, because it forces a programmer to completely rethink the approach to designing an application. The reward is reusable code. Since this is a hands on tutorial, I plan to show you how the M-VC architecture promotes code reuse by migrating a Windows Form solution to a browser based solution using a Web Form.

The Model -- View/Controller architecture is a modification of the Model -- View -- Controller architecture used in the SmallTalk language. In the SmallTalk language, the application is divided into three parts. The Model encapsulates the application logic or algorithms. The View draws the presentation. The Controller responds to user or system events. The key concept is the separation of the application logic from the presentation and event handling code. The Model class is independent of the GUI and is ignorant of any implementation of the GUI. A good Model class should be able to function as part of a console application and support unit testing. In this chapter, you will build an application that separates the complex mathematics of a mortgage calculator (Model) from the presentation and event handling code (View/Controller). The code behind technique of Web Form programming further contributes to the separation of the View (HTML code) and Controller (code behind event handler) code. There is no question that the complete separation of GUI code from the application logic is a difficult concept for many to grasp. It can be a painful learning experience as it forces a programmer to change the basic approach to application design. Many will fight the process, dragged into the new world of OOP kicking and screaming. But, when you see how much simpler a Model -- View/Controller application is to maintain or migrate, you will _see_ the light. I promise. The Model Class The following code was adapted from our book "Visual Cafe for Java Explorer, Database Development Edition" Brogden, Louie, Tittel, Coriolis, 1998. The only real change from the Java version is the use of C#'s support for "properties." The Model class implements the algorithms of a mortgage calculator. The fact that the Java code was completely separate from the Java GUI greatly simplified the reuse of this 1997 code in this C# Windows Form application! In a nutshell, given three of four mortgage parameters (principal, interest, period in months, payment), you can calculate the unknown parameter. Solving for interest is not a trivial mathematical solution. I readily admit that I had help solving that equation from my good friend, Dr. W. Carlini! The Model class has an "Init" method that takes all four parameters needed for a mortgage calculator. One and only one parameter must have a value of zero. The zero parameter acts as a marker for the unknown value. This class also demonstrates the use of two common programming idioms: the use of a public "IsValid" function to return the internal state of the object and the use of pre and post conditions to validate the input and output of an algorithm. Using IsValid() Note that all of the actual calculations occur on a call to the "Init" method, either directly or indirectly through the "args" constructor. If the input parameters and result appear valid, the "target" variable is set to a valid value. If the input parameters or result appear invalid, the "target" variable is set to -1. A public function "IsValid" is provided to the caller that returns the internal state of the object. The public function "IsValid" encapsulates or hides the internal validation logic. I would argue that the use of a public "IsValid" function is a common and useful programming idiom. Pre and Post Conditions The downside of separating out the algorithm from the GUI, is that both the Model class and the View/Controller class does input checking to insure runtime reliability and useful user feedback. The Model class implements a common programming construct, the use of pre and post conditions. In the Model class, the "Init" method statically validates the input parameters before passing them on to the DoAlgorithm method (pre-conditions). The algorithm does not check for a divide by zero error, which is handled internally. After the calculation is complete, the

"DoAlgorithm" method validates the result by calling Double.IsNaN (IsNotANumber) (postconditions). The decision to turn off pre and post conditions in the release build (no check version) is beyond the scope of this tutorial. The compulsive coder will note the the input validation scheme is not mathematically correct, rejecting interest rates of greater than 100%. Apparently the twisted class has a social agenda. Complete Code Listing Model.cs The downside of posting all of the code is that it goes on forever. Click here to skip the code. You can come back later.

/// <summary> /// Class Model.cs /// jlouie 07.07.02 /// Adapted from Model.java /// "Visual Cafe for Java Explorer, Database Development Edition" /// William Brogden, Jeffrey A. Louie, and Ed Tittel, Coriolis, 1998, 585pp. /// Supplied "as is" /// No warranty is expressed or implied /// This code is for instructional use only /// </summary> public class Model { // internal class constants, not "versionable" private const int INVALID= -1; // flags error private const int PRINCIPAL= 0; private const int INTEREST= 1; private const int MONTHS= 2; private const int PAYMENT= 3; private double[] arrayDb= new double[4]; private int target= INVALID; private string message= ""; /* // uncomment to run console self test // self test static method outputs state to console static void ConsoleDebug(Model model) { if (model == null) { System.Console.WriteLine("Null object."); return; } System.Console.WriteLine("Message: "+model.Message); System.Console.WriteLine("Result: "+model.Result); System.Console.WriteLine("Principal: "+model.Principal); System.Console.WriteLine("Interest: "+model.Interest); System.Console.WriteLine("Months: "+model.Months); System.Console.WriteLine("Payment: "+model.Payment); } */ /* // uncomment to run console self test // self test [STAThread] static void Main() {

// test internal consistency of algorithms Model model= new Model(100000,8.5,360,0); Model.ConsoleDebug(model); // payment = 768.9134584334 model.Init(0,8.5,360,768.9134584334); Model.ConsoleDebug(model); model.Init(100000,0,360,768.9134584334); Model.ConsoleDebug(model); model.Init(100000,8.5,0,768.9134584334); Model.ConsoleDebug(model); System.Console.ReadLine(); }*/ // no arg constructor public Model(){;} // arg constructor public Model(double principal, double interest, int months, double payment) { Init(principal, interest, months, payment); } // factored code, can be called after call to constructor // allowing reuse of instance of class // eg. object is _not_ immutable by design public void Init(double principal, double interest, int months, double payment) { // reset flags target= INVALID; message= ""; // store input into array of double arrayDb[PRINCIPAL]= principal; arrayDb[INTEREST]= interest; arrayDb[MONTHS]= (double)months; arrayDb[PAYMENT]= payment; // validate input // one, and only one, "value" must be zero --> target int zeros= 0; int tempTarget= INVALID; for (int i=0; i<4; i++) { if (arrayDb[i] == 0) { zeros++; tempTarget= i; } } if (zeros>1) { message= "Too many zero parameters."; return; } if (zeros == 0) { message= "One parameter must be zero."; return; } // validate interest

if (interest > 100 || interest < 0) { message= "Invalid interest."; return; } // validate months if (months < 0) { message= "Invalid months."; return; } // validate principal if (principal < 0) { message= "Invalid principal."; return; } // validate payment if (payment < 0) { message= "Invalid payment."; return; } // input parameters appear valid target= tempTarget; DoAlgorithm(target); } // the actual amortization algorithm // m= P*i(1-(1+i)^-N) // i=r/1200 // result= 0 --> marks error private void DoAlgorithm(int target) { double result= 0; double P= arrayDb[PRINCIPAL]; // principal double i= arrayDb[INTEREST]/1200; // monthly percentage rate double N= arrayDb[MONTHS]; // loan period in months double m= arrayDb[PAYMENT]; // monthly payment if (target>= 0 && target< 4) // validate target { try { switch (target) { case PRINCIPAL: // principal result= 1+i; result= 1/Math.Pow(result, N); result= ((1-result)/i)*m; break; case INTEREST: // annual interest // algorithm fails if N*m >= P !! if ((N*m)<P) { throw new ArithmeticException(); } // factor out Interest function, too long

result= CalcInterest(P,N,m); break; case MONTHS: // loan period result= (1-(P*i/m)); result= Math.Log(result); result= -result/Math.Log((1+i)); break; case PAYMENT: // monthly payments result= 1+i; result= 1/Math.Pow(result,N); result= (P*i)/(1-result); break; //default: //break; } } catch { result= 0; } } // validate result if (Double.IsNaN(result)) { result= 0; } if (result == 0) { message= "Input Error."; } else // valid result { arrayDb[target]= result; } } // a complex iterative calculation for interest // thanks to Dr. W. Carlini (and Newton)for the solution // returns zero on error // ASSERT (N*m)>=P private double CalcInterest(double P, double N, double m) { double temp= (m/P), answer= (m/P), diff= 100, numerator= 0, denominator= 0, accuracy= .00001; int index, maxIterations= 1000; try { for (index= 0; ((diff>accuracy) && (index<maxIterations)); index++) { temp= answer; numerator= (P*temp/m)+Math.Pow((1+temp),-N)-1; denominator= (P/m)-N*Math.Pow((1+temp),(-N-1)); // if (denominator ==0 ){throw new ArithmeticException();} answer= temp-(numerator/denominator); diff= answer- temp;

if (diff<0) { diff= -diff; } } answer *= 1200; // validate answer if ((answer<0) || Double.IsNaN(answer) || (index == maxIterations)) { throw new ArithmeticException(); } } catch { answer= 0; } return answer; } // default target is -1 (INVALID) public bool IsValid() { return ((target>=PRINCIPAL) && (target<=PAYMENT)) ? true: false; } // Java "getter" code converted to C# get only properties public double Result { get { if (IsValid()) { return arrayDb[target]; } else { return 0.0; } } } public int Target { get { return target; } } public string Message { get { return message; } } public double Principal { get { if (IsValid())

{ } else { }

return arrayDb[PRINCIPAL];

return 0.0;

} } public double Interest { get { if (IsValid()) { return arrayDb[INTEREST]; } else { return 0.0; } } } public double Months { get { if (IsValid()) { return arrayDb[MONTHS]; } else { return 0; } } } public double Payment { get { if (IsValid()) { return arrayDb[PAYMENT]; } else { return 0.0; } } }

Creating a Windows Form Application

I fired up the Visual Studio IDE, dragged a few controls around and wired up two event handlers. This is what I got:

You could certainly spiff up this application by adding radio buttons that let the user select the target of the calculation. You could then disable the appropriate input control, setting the value of the target control to zero. Interestingly, the Parse method happily accepts embedded commas. In the application you simply create an instance of the Model class:

private Model model= new Model();


You then call the appropriate Model methods and properties in the buttonCalculate and buttonReset event handlers:

private void buttonCalculate_Click(object sender, System.EventArgs e) { double principal= 0; double interest= 0; int months= 0; double payment= 0; bool isInputError= false; // validate user input, must allow zero try { principal= Double.Parse(textBoxPrincipal.Text); if (principal<0) { throw new Exception(); } }

catch { textBoxPrincipal.Text= "Invalid Input."; isInputError= true; } try { interest= Double.Parse(textBoxInterest.Text); if ((interest < 0) || (interest > 100)) { throw new Exception(); } } catch { textBoxInterest.Text= "Invalid Input."; isInputError= true; } try { months= Int32.Parse(textBoxPeriod.Text); if (months <0) { throw new Exception(); } } catch textBoxPeriod.Text= "Invalid Input."; isInputError= true; } try { payment= Double.Parse(textBoxPayment.Text); if (payment < 0) { throw new Exception(); } } catch textBoxPayment.Text= "Invalid Input."; isInputError= true; } if (isInputError) { return; } // valid user input model.Init(principal,interest,months,payment); if (model.IsValid()) { textBoxPrincipal.Text= model.Principal.ToString(); textBoxInterest.Text= model.Interest.ToString(); textBoxPeriod.Text= model.Months.ToString(); textBoxPayment.Text= model.Payment.ToString(); textBoxMessage.Text= model.Message.ToString(); } else

} } private void buttonReset_Click(object sender, System.EventArgs e) { textBoxMessage.Text= ""; ResetControls(); } private void ResetControls() { textBoxPrincipal.Text= ""; textBoxInterest.Text= ""; textBoxPeriod.Text= ""; textBoxPayment.Text= "0"; textBoxPrincipal.Focus(); }
Creating a Web Form Application Just to prove how easy it is to reuse the Model class, I then fired up the IDE and built a browser based version of the mortgage calculator. Just think. If your client suddenly wakes up one day and ask for a browser based version of your application, you won't be having a panic attack. By separating out the application logic from the GUI (view and event handling code), you are prepared for code reuse. Here is a snapshot of the browser based calculator:

textBoxMessage.Text= model.Message.ToString(); ResetControls();

Now it's your turn to do some coding. Just create a new Windows Form or Web Form application and copy and paste the Model class into your project. You will need to remove any embedded carriage returns that were added to the actual code for easy HTML viewing. If you want to download the working projects, they are available at http://www.geocities.com/jeff_louie/download.html Hopefully, I have convinced you of the need to separate out your application logic from the presentation and event handling code. I have reused the Model code from a Java application in both a Windows Form and Web Form application. Use this most basic design pattern, the Model -- View/Controller architecture. It will grow on you!

Static Methods, Factories & Constructors


Well, I've tried as long as possible to avoid the the "nuts and bolts" of object oriented programming. It's sort of like going in to the dentist for a root canal. You know it needs to be done, but it is going to be painful and you want to put it off. The good news is that once you have the root canal the pain goes away! So just dive in. In this chapter you will learn about static methods, factory methods and constructors. You will be introduced to the creational patterns "Class Factory" and "Singleton". What Is a Static Field or Method?

Let's change the question. When is a field or method not part of an object? Answer: when it is part of the class! Remember, an object is an instance of a class and each object exists in a separate space in memory. It is possible to access class fields and class methods without creating an instance of a class using the "static" key word. Declaring a field or method with the static key word, tells the compiler that the field or method is associated with the class itself, not with instances of the class. In a sense, static or "class" fields and methods are global variables and methods that you can touch using the class name. If you think of a class as a blueprint used to create objects, then you can think of static fields and methods are being part of the blueprint itself. There is only one copy of the static fields and methods in memory, shared by all instances of the class. Static fields are useful when you want to store state related to all instances of a class. A counter is a good example of a static field. The classic use of a static counter is to generate a unique ID or serial number for each instance of a class. Static methods are useful when you have behavior that is global to the class and not specific to an instance of a class. In contrast, instance methods are useful when the method needs to know about the state of an object. Since data and behavior are intertwined in an object, instance methods have access to the instance fields and can exhibit behavior that is specific to the state of an object. A Static Counter Here is the classic example of a static counter that is zero based. It contains a static field "uniqueID" and a thread safe static method "GetUniqueID" that increments the unique ID:

/// <summary> /// Summary description for TestStatic. /// </summary> class TestStatic { // static stuff private static int uniqueID= 0; private static int GetUniqueID() { lock(typeof(TestStatic)) { return uniqueID++; // returns zero at start } } // member stuff private int identity; public TestStatic() { this.identity= TestStatic.GetUniqueID(); } public int Identity { get { return identity; } } } public class Test {

/// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // TestStatic ts1= new TestStatic(); TestStatic ts2= new TestStatic(); Console.WriteLine(ts1.Identity.ToString()); Console.WriteLine(ts2.Identity.ToString()); Console.ReadLine(); }

If you compile and run this code the output is: 0 and 1. The static field "uniqueID" is global to the application and stores the value of the next unique ID. Each call to the constructor returns the unique ID and then increments the counter using the "postfix" operator ++. Notice how you use the class name to touch a static field or method:

ClassName.fieldName; ClassName.MethodName();
Note: In Java you can touch a static field or method using the class name or a reference variable to an instance of a class. Not so in C#. Managing Concurrency Conflicts The curious coder will note the call to "lock" which causes callers of the static method "GetUniqueID" to queue up to this method. (Lock is basically a shortcut to "Monitor.Enter" and "Monitor.Exit".) Locking inside the method insures that the method is thread safe. The problem is that the increment operator (++) is not an atomic operation, but performs a read and then a write. If you don't force callers to queue up to the increment operation it is possible for two callers to "almost simultaneously" enter the method. Both callers could read the uniqueID value before either caller can write the incremented value. In this case, both callers will receive the same ID. Not very unique! Be careful. If your locking code is poorly written, it is possible for two callers to queue up in a "catch-22" conflict where neither call can proceed, an example of "deadlock." The topic of locking, deadlock, and concurrency is an advanced topic not covered by this tutorial. Let's Get Constructed When you create an instance of an object using the key word "new", you call a class constructor. In fact, if you don't explicitly declare a class constructors, the compiler creates a hidden no argument constructor for you. Here is an example of explicitly declaring a no-arg do nothing constructor:

class Toaster { public Toaster() {} // this is a do nothing constructor }

The compiler will create this constructor, if and only if, you do not declare any constructors for the class. The syntax for a public constructor is:

public NameOfClass(parameterList) { ... stuff here }


Let's Get Initialized Constructors are often used to initialize the state of an object. Alternatively, you can initialize the instance fields when they are declared. Finally, you can break out the initialization code into a separate "Init" method. The following code demonstrates all three idioms for initializing an object:

/// <summary> /// Summary description for Idioms ./// </summary> class Idioms { private Hashtable idiom1= new Hashtable(); private Hashtable idiom2; private Hashtable idiom3; /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // Idioms c= new Idioms();} public Idioms() { Init(); idiom2= new Hashtable(); } private void Init() { idiom3= new Hashtable(); } }
Assigning an instance variable a value when you declare the variable is an example of defensive programming. It minimizes the chance of forgetting to initialize a variable in the constructor or Init method. Creating Multiple Constructors A common programming task is to create multiple constructors that differ only in their parameter list. The C# language supports this concept by allowing you to "overload" a method name. As long as the parameter list is sufficiently unique, you can create multiple methods or constructors with the same name.

Note: Be careful not to confuse overloading with overriding. Overriding a virtual method is quite different than overloading a method or constructor. Overriding is a subject of a future tutorial. I promise. It's time to resurrect the Toaster class. Here is a new version of the Toaster class with two new instance fields that contain information about the color of the toaster and the model name of the toaster:

class Toaster { public const string DEFAULT_NAME= "Generic"; public enum ColorType {Black, Red, Yellow, White}; private static ColorType DEFAULT_COLOR= ColorType.Black; private ColorType color= DEFAULT_COLOR; private string modelName= DEFAULT_NAME; }
Note the use of an enum "ColorType" to limit the domain of valid toaster colors. Here again is the default no-args constructor:

public Toaster(){} // black toaster with default name


The no-arg constructor simply leaves the default field values unaltered. You can now create a constructor that takes two parameters, the color type and the model name. Note that the constructor does validity checking to insure that the state of the object remains valid.

public Toaster(ColorType color, string modelName) { this.color= color; if (modelName != null) { this.modelName= modelName; } }
You can now create a constructor that only takes one parameter, the model name:

public Toaster(string modelName) { if (modelName != null) { this.modelName= modelName } }


Now this looks like redundant code, just begging to be refactored. Happily, C# allows you to chain constructor calls, eliminating the redundant null checking code. You can chain the two constructors like this:

public Toaster(string modelName) : this(DEFAULT_COLOR, modelName) {}


The syntax is:

public ClassName(someParameters) : this(someParameters) {}


Pretty cool! By using C#'s built in support for constructor overloading and constructor chaining you can write a series of constructors. Here is the final version of the Toaster class using multiple overloaded constructors:

class Toaster { public const string DEFAULT_NAME= "Generic"; public enum ColorType {Black, Red, Yellow, White}; private static ColorType DEFAULT_COLOR= ColorType.Black; private ColorType color= DEFAULT_COLOR; private string modelName= DEFAULT_NAME; public Toaster(){} // black toaster with default name public Toaster(ColorType color, string modelName) { this.color= color; if (modelName != null) { this.modelName= modelName; } } public Toaster(ColorType color) : this(color,DEFAULT_NAME){} public Toaster(string modelName) : this(DEFAULT_COLOR,modelName) {} public string Color { get { return Enum.Format(typeof(ColorType), color,"G"); } } public string ModelName { get { return modelName; // danger, return ModelName --> stack overflow! } } }
What Is a Destructor? C++ programmers are familiar with the concept of a destructor. I only briefly mention this topic here in self defense. In C++, a destructor is a method that is called when an object goes out of scope, is deleted, or the application closes. In C++, a destructor is often used to release valuable system resources. This works in C++ since memory reuse in C++ is deterministic. When an object in C++ goes out of scope, the destructor is called and resources can be released immediately. Things are quite different in C#. First, memory reuse in C# is based on garbage collection. In a nutshell, when application memory becomes limited, the garbage collector executes and attempts to reclaim memory by reclaiming objects that are not "reachable". As a result, in C#, you cannot depend on a destructor to reclaim system resources in a timely manner.

Second, although C# supports the syntax of destructors, destructors in C# simply map to finalize. According to the IDE documentation:

~ MyClass() { // Cleanup statements. }


... is converted by the compiler to:

protected override void Finalize() { try { // Cleanup statements. } finally { base.Finalize(); } }


If your object uses valuable external resources, you may want your class to inherit from the IDisposable interface and implement the Dispose method, calling GC.SuppressFinalize. Alternatively, you want to rely on C#'s support for try, catch, finally to release external resources. For instance, you might want to open a connection in try and close any open connections in finally. The concept of garbage collection and reclaiming external resources is definitely beyond the scope of this tutorial. Using Static Factory Methods Instead of Multiple Constructors You might wonder why I have chosen to combine the topics of static methods and constructors into a single chapter. The answer is "static factory methods." Instead of writing multiple public constructors, you can write multiple static factory methods and private constructors that return objects. First, here is an example of a static factory method. The method simply constructs an object with default values and then returns a reference to the object.

public static Toaster GetInstance() { return new Toaster(ColorType.Black, DEFAULT_NAME); }


In a sense, this static method is analogous to the no-arg constructor.

public Toaster() {}
Here is the version of the Toaster class that uses static methods and a single private constructor to return toaster objects:

/// <summary> /// Summary description for Toaster /// </summary>

class Toaster { // static factory methods public static Toaster GetInstance() { return new Toaster(ColorType.Black, DEFAULT_NAME); } public static Toaster GetInstance(string modelName) { return new Toaster(ColorType.Black, modelName); } public static Toaster GetInstance(ColorType color) { return new Toaster(color, DEFAULT_NAME); } public static Toaster GetInstance(ColorType color, string modelName) { return new Toaster(color, modelName); } public const string DEFAULT_NAME= "Generic"; public enum ColorType {Black, Red, Yellow, White}; // black is the enum default value! private static ColorType DEFAULT_COLOR= ColorType.Black; private ColorType color= DEFAULT_COLOR; private string modelName= DEFAULT_NAME; // the single private constructor private Toaster(ColorType color, string modelName) { this.color= color; // ColorType cannot be null --> compile time error or defaults to ColorType.Black! if (modelName != null) { this.modelName= modelName; } } // the getters public string Color { get { return Enum.Format(typeof(ColorType), color,"G"); } } public string ModelName { get { return modelName; // danger, return ModelName --> stack overflow! } } }
Declaring the only constructor private, prevents any outside caller from directly instantiating the class. The only path to a Toaster object is through a static factory method. So, you can use multiple overloaded public constructors or multiple static factory methods and private constructors to create toaster objects. If you are interested in learning more about using static

factory methods instead of multiple constructers check out Effective Java Programming Language Guide by Joshua Bloch, Addison-Wessley, 2001, 252 pp. Note: The behavior of enum is quite complicated. You cannot set an enum to null and if you fail to explicitly initialize an enum variable, it defaults to the first member of the enumeration. For example:

public static ColorType c; // c --> ColorType.Black


Creational Patterns -- Class Factory and Singleton I am going to finish off this chapter by introducing two common design patterns: the "Class Factory" and "Singleton" patterns. The class factory is useful when you want to return concrete objects that share a base class, at runtime. The singleton pattern is useful when you only want to allow the creation of one instance of an object in a application. These patterns are both considered "Creational" patterns since they abstract the creation of objects. Using a Static Method to Return Concrete Classes -- The Class Factory. The concept of using static methods to return objects is a useful one. In the previous code, you learned how to replace multiple constructors with multiple static factory methods. Another useful design pattern is the "Class Factory." A class factory can be used to return concrete implementations of a common base type. In Chapter 2, you learned about polymorphism using the Drawable abstract class. Concrete implementations of the Drawable class such as square or circle provide a concrete implementation of the abstract "DrawYourself" method. Let's resurrect our Drawable class.

abstract class Drawable { public abstract String DrawYourself(); } class Circle : Drawable { public override String DrawYourself() { return "Circle"; } } class Square : Drawable { public override String DrawYourself() { return "Square"; } }
In this example of the class factory pattern, you pass a parameter to a static factory method that then returns the appropriate concrete implementation of the Drawable abstract class. To insure that the method is passed valid parameters at compile time, you can define a type safe enum "DrawableType":

public enum DrawableType {CIRCLE,SQUARE};


Here is our class factory:

/// <summary> /// Summary description for class Factory. /// </summary> class Factory { public enum DrawableType {CIRCLE,SQUARE}; public static Drawable GetInstance(DrawableEnum e) { if (e == DrawableType.CIRCLE) { return new Circle(); } else if (e == DrawableType.SQUARE) { return new Square(); } else { throw new IndexOutOfRangeException(); // should never get here } } /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // Drawable d1= Factory.GetInstance(Factory.DrawableType.CIRCLE); Console.WriteLine(d1.DrawYourself()); Drawable d2= Factory.GetInstance(Factory.DrawableType.SQUARE); Console.WriteLine(d2.DrawYourself());Console.ReadLine(); } }
Note that d1 and d1 are reference variables of the Type Drawable, yet the code outputs: Circle, Square. Polymorphism at work! The class factory design pattern allows your application to create concrete implementations of a base class or interface dynamically at runtime in response to user or system input. The Singleton Pattern The "Singleton" pattern is a special version of the class factory that only returns a single instance of a class. The singleton pattern is useful when there should only be one instance of an object. As an example, there may be many soldiers that derive from person, but there should only be one reigning King of England that derives from person! Here is a sample that uses a static factory method to insure that only one instance is created. The factory method "GetInstance" returns a reference to the single instance of the class. Note that you must declare any constructors private, so that the constructors are not visible outside of the class. This insures that. there will be one and only one instance of MyClass.

/// <summary> /// Summary description for MyClass.

/// </summary> class MyClass { private static MyClass theOnlyOne= new MyClass(); // create one and only one instance of the class public static MyClass GetInstance() { return theOnlyOne; } public readonly string description= "The One and Only."; private MyClass(){} /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // MyClass mc= MyClass.GetInstance(); Console.WriteLine(mc.description); Console.ReadLine(); } }
One of the advantages of the factory method is that you can modify the singleton behavior of the class without affecting the caller of the class. If you decide that your application should now support Kings present and past, then you can modify MyClass to return a new instance for each call to GetInstance. Here is the modified multi-instance version of MyClass:

/// <summary> /// Summary description for MyClass /// </summary> class MyClass { public static MyClass GetInstance() { return new MyClass(); } public readonly string description= "OneOfMany"; /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // MyClass mc= MyClass.GetInstance(); Console.WriteLine(mc.description); Console.ReadLine(); } }

That's enough pain! I suggest the you jog around the block, clear your head and re-read this chapter later. In the next chapter, you will learn the top ten "gumption traps" for C++ and Java programmers.

C++ and Java Gumption Traps


It's time for another break from theory and on to some real world programming challenges. In this chapter, you take a detour into the world of gumption traps. A gumption trap is a situation that is so frustrating that it sucks the "gumption" or energy out of you. Surprisingly, a lot of gumption traps come from preconceived notions of what "should" be correct. C++ and Java programmers are prone to gumption traps due to their assumptions about the C# language. In other words, C++ and Java programmers have a bit of "language baggage" that needs to be left behind. So, if you have a language neurosis, this chapter is for you. Top Ten C++ Gumption Traps In no particular order. 1) Arrays in C# are Objects In C#, arrays are objects derived from System.Array. The following code snippet creates an array object that can contain ten elements of MyClass:

MyClass[] arrayMC= new MyClass[10];


What may surprise you, is that this call does not create any instances of MyClass! In fact, if you iterate over the array, you will find that the array contains ten null elements. To fill the array, you must explicitly create ten instances of MyClass and fill the array:

MyClass[] arrayMC= new MyClass[10]; [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // Class1 c1= new Class1(); for (int i=0; i<10; i++) { c1.arrayMC[i]= new MyClass(); } Console.ReadLine(); }
2) Declaring an Object Simply Creates an Un-initialized Object Variable In C++, when you declare an object, the object is created. Not so in C#. The following code simply declares an un-initialized reference variable of Type MyClass. The variable occupies memory on the stack to hold an address. No object is created on the heap. If you try to use c, the compiler will complain that the variable has not been initialized.

MyClass c;

The following code snippet, creates a variable and initializes the variable to null, so that the reference does not refer to any object. If you try to use the reference variable to touch a field or method of the class, the code will throw a null reference exception.

MyClass c= null;
So, if you want to declare and initialize a reference variable and create an object in C# you must use the new keyword like this:

MyClass c= new MyClass();


"c" is now a reference variable of Type MyClass. If this is a local variable, then "c" uses memory on the stack which contains the address of an object of Class MyClass on the heap. As discussed earlier, the string class (strings are immutable and shared) is an exception to the rule. You can create a string like this:

string s= "Hello";
3) C# Uses Automatic Garbage Collection, Destructors are not Deterministic The call to new may bother a C++ programmer who may now feel obligated to call delete appropriately. All I can say is lighten up! Objects are (mostly) reclaimed automatically in C#. In a nutshell, when available memory falls, the garbage collector is called, freeing up any objects that are unreachable. If you are done with an object, you can assist the garbage collector by releasing all references to the object. Even if two objects contain references to each other (circular references), the objects can still be collected if they become "unreachable." Since objects in C# are garbage collected, it is not a good idea to reclaim resources in the destructor. A destructor will not be called until the object is reclaimed by the garbage collector. In other words, destructors are not deterministic in C#. Critical external resources are best released by inheriting from IDisposable and implementing the Dispose method, or by using C#'s try, catch, finally construct to insure that any allocated resources are reclaimed in the finally clause. Here is a twisted example of try, catch, finally in C#:

try {

} catch(OverflowException e) { CallPlumber(); } finally { CloseToiletLid(); }


4) The Assignment Operator Does Not Call the Copy Constructor This one really confuses a lot of coders. In C# the assignment operator simply assigns a reference variable to an existing object, to a new object, or to null. After the assignment, the reference variable contains a reference to an object or to no object (is null). The assignment operator does not call the copy constructor to create a new object. It is quite legal in C# to have

OpenToiletLid(); Flush();

two reference variables that contain references to the same object. The two variables occupy different memory locations on the stack, but contain values that point to the same memory address on the heap. Both references would have to be released (e.g. the reference variables go out of scope, be reassigned, set to null) before the object can be reclaimed. As a result, the "destructor" will only be called once. The following code simply creates two references to the same object:

MyClass c1= new MyClass(); MyClass c2; c2= c1; bool isSameReference= (c1 == c2); // c1 and c2 contain references to the same object on the heap Console.WriteLine(isSameReference.ToString()); // output--> true
Be clear that if variable c1 contains the only reference to an object, setting c1 to null or reassigning c1 to another object will make the original object unreachable and eligible for garbage collection. 5) Values and References to Objects are Passed By Value By default, objects in C# are not passed by reference. (Unlike Java, C# does support passing by reference using the ref keyword.) In C#, you pass a reference or a value to a method. You cannot pass an object to a method. By default, all calls to methods are by value. Now is that clear! In other words, you pass a reference to an object to a method, not the object itself. The reference is passed by value so that the a copy of the reference goes on the stack. The key here is that the object is not copied onto the stack and you can touch the object while inside the method. If you want to truly pass an object by reference (for a swap routine) use the ref keyword. Remember, you cannot pass an object, so you are actually passing a reference by reference. Oh, I have a headache. 6) Const is Hard Coded Into the Caller and not Version-able I find this one a bit weird. A const field value is hard coded into the caller for optimization so that the value is not updated until you recompile the caller. If you want to version-able read only field declare it readonly. Finally, you can provide a get only Property like this:

public string ModelName { get { return modelName; // danger, return ModelName --> stack overflow! } }
7) Supports Single Inheritance of Implementation and Multiple Inheritance of Interfaces C# does not support multiple inheritance of implementation. It does support multiple inheritance of interfaces (pure virtual classes) and single inheritance of implementation. 8) Program to Return Single Values Although C# does support an out parameter, in general, C# programs are designed to return single values. Consider redesigning your application or returning immutable objects.

9) Strings are Immutable The string class is a very special class. First strings are immutable. Every time you concatenate a string, you may be creating a new string object. If you want a mutable class, use StringBuilder. Second, you can create a string object using the assignment operator. Third, strings are shared so that two strings that you create may occupy the same space in memory. Fourth, the equality operator is overloaded for string and checks for content equivalence, not "reference based equality." Note: The overloaded string equality operator only works on reference variables of Type string. Be careful! Thanks to Jon S. for this insight.

object a= "Hello"; object b= "Hello"; bool isSameReference= (a == b); // test if a and b contain references to the same object or to no object (are both null) bool isSameContent= ((string)a == (string)b); // test if string referenced by a and string referenced b have the same content/value or a and b are both null Session["KEY"]="VALUE"; // Error! The left hand operand is of type object! This is a reference based comparison. Do this: (String)Session["KEY"]="VALUE"; // content equivalence
10) bool is a Value Type C# has a built in type for Boolean which can have a value true or false. The default value of bool is false. Enough said. Top Ten Java Gumption Traps In no particular order. 1) No Checked Exceptions The compiler in C# will not enforce catching of any checked exceptions. So there is no support for declaring a checked exception (no throws keyword). 2) All Methods are Not Virtual By Default. All Members are Private by Default. In Java, all methods are virtual by default and can be overridden. Not so in C#. You must explicitly declare a method virtual if you want it to allow it to be overridden. You also cannot implicitly override or hide a virtual method, but must explicitly use the override or new keyword. In Java, members have package level access by default. In C# all members are private by default. 3) Const, ReadOnly and Get Only I find this one a bit weird. A const field value is hard coded into the caller for optimization so that the value is not updated until you recompile the caller. If you want to version-able read only field declare it readonly. Finally, you can provide a get only Property like this:

public string ModelName {

get { return modelName; // danger, return ModelName --> stack overflow! } }


4) All Types in the NET Framework Derive from Object C# has a unified type system so that all reference and value types derive from Object. For instance, int is an alias for System.Int32. As a result, you can call ToString() on any value or reference type. This simplifies debugging in the Console mode. 5) The Visual Studio IDE Startup Object is Empty By Default If the startup object string is empty and you declare more than one "Main" method in a Visual Studio project, the project will not compile. This is very frustrating. Trying to set the startup object property in the Visual Studio IDE is non-trivial. Let me save you some pain. To set the startup object, select View --> Solution Explorer. In the Solution Explorer window select the name of the project. Now select View --> Property Pages. (Do not select the Property Window!) Alternatively, right click on the project name and select Properties. Now select the Common Properties folder in the left window. You can now select the appropriate startup object from the drop down list. Don't forget to click on "Apply." 6) Method Names Start with Upper Case This one is pretty self explanatory. 7) Getters and Setters are Implemented Using Properties, Which are Upper Case C# formally supports the concept of getters and setters with Properties. Note that properties are upper case by convention. Here are the setter and getter methods as properties:

// Properties public int SecondsToToast { get {return secondsToToast;} // danger, return SecondsToToast --> stack overflow! set { if (value > 0) { secondsToToast= value; } else { secondsToToast= 0; } } }
The reserved word value is used to represent the callers input. Note the syntax used to call a property. To set a property use:

t.SecondsToToast= 12;

8) Use "is" instead of "instanceof", ArrayList instead of ArrayList/Vector, StringBuilder instead of StringBuffer, Hashtable instead of HashMap/Hashtable, System.Environment.NewLine instead of line.separator.. Just trying to save you some headaches. 9) There is an "enum" Java evolved before the concept of type safe enum. C# has built in support for type safe enums like this:

public enum ColorType {Black, Red, Yellow, White}; private static ColorType DEFAULT_COLOR= ColorType.Black;
You can still create a custom enum in C# like this:

sealed class MyEnum { private String name; private static int nextOrdinal= 1; private int ordinal= nextOrdinal++; private MyEnum(String name) { this.name= name; } public override String ToString() { return name; } public int ToOrdinal() { return ordinal; } public static MyEnum INVALID= new MyEnum("Invalid"); // ordinal 1 public static MyEnum OPENED= new MyEnum("Opened"); // ordinal 2 public static MyEnum CLOSED=new MyEnum("Closed"); // ordinal 3 /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // Console.WriteLine(MyEnum.OPENED.ToString()); Console.WriteLine(MyEnum.OPENED.ToOrdinal().ToString()); Console.WriteLine(MyEnum.INVALID.ToString()); Console.WriteLine(MyEnum.INVALID.ToOrdinal().ToString()); Console.WriteLine(MyEnum.CLOSED.ToString()); Console.WriteLine(MyEnum.CLOSED.ToOrdinal().ToString()); Console.ReadLine(); } }

10) String Equality Operator is Overridden for Content Comparison Thankfully, the string equality operator in C# has been overloaded and checks for content/value equivalence. One less gotcha for the C# novice. Note: The overloaded string equality operator only works on reference variables of Type string. Be careful! Thanks to Jon S. for this insight.

object a= "Hello"; object b= "Hello"; bool isSameReference= (a == b); // test if a and b contain references to the same object or to no object (are both null) bool isSameContent= ((string)a == (string)b); // test if string referenced by a and string referenced b have the same content/value or a and b are both null Session["KEY"]="VALUE"; // Error! The left hand operand is of type object! This is a reference based comparison. Do this: (String)Session["KEY"]="VALUE"; // content equivalence
OK, boys and girls. It's not your father's language. Get over it<g>. The Equality Operator Revisited Thanks to Jon S. I have revisited the concept of equality on operands of the reference type. The equality operator, in general, compares operands by reference. The string equality operator is overloaded to compare operands by value. In plain English, the equality operator normally checks to see if two object variables refer to the same object on the heap. The string equality operator is overloaded to check for content or value equivalence. In not so plain English, the equality operator normally checks to see if two reference variables contain references to the same object on the heap. In C# local reference variables go on the stack and contain the address of the object on the heap. So local reference based equality in C# checks to see if two reference variables, stored on the stack, contain addresses which are equal. In other words, it checks for address equality. This is referred to as "reference based" equality or "compare by reference" or "referential equality". Whew! As previously stated, the string equality operator is overloaded to check for value or content equivalence. In not so plain English, the string equality operator compares the content or value of string objects on the heap. It does this by obtaining the address of the objects from the values of the reference variables stored on the stack. Now I would like to simplify this discussion to that of "object" equality vs. "content" equality, but I cannot! By convention, object equality refers to content equality! I would also like to reduce this discussion to referential "equality" vs. content "equivalence", but I cannot. Unfortunately, by convention, the Equals() method is used to determine content equivalence!

Objects Have Class, References Have Type


Well, you have arrived. If you have survived to this point, you are beginning to realize both the power and complexity of programming using objects and inheritance. Much of the confusion about references, types, classes and objects is simplified by the following statement "Objects have class, references have type." The more technically correct version may be "Objects have class, reference variables have type." As long as it is understood that reference variables "contain" references to objects, the former statement is a superior in its simplicity.

What is a Type? There are a number of definitions of a type, but I have struggled to find an illuminating statement. According to Grady Booch (Object Oriented Analysis and Design) type is "The definition of the domain of allowable values that an object may possess and the set of operations that may be performed upon the object. The terms class and type are usually (but not always) interchangeable; a type is a slightly different concept than a class, in that it emphasizes the importance of conformance to a common protocol... Typing lets us express our abstractions so that the programming language in which we implement them can be made to enforce design decisions." According to Bertrand Meyer (Object-Oriented Software Construction) "A type is the static description of certain dynamic objects: the various data elements that will be processed during execution of a software system...The notion of type is a semantic concept, since every type directly influences the execution of a software object by defining the form of the objects that the system will create and manipulate at run time." According to the "Gang of Four" (Design Patterns) "The set of all signatures defined by an object's operations is called the interface to the object... A type is a name used to denote a particular interface.... An object may have many types, and widely different objects can share a type.... An object's interface says nothing about its implementation--different objects are free to implement requests differently." It is the last definition that emphasizes the concept of programming to an interface, one or more public views of an object. You can look at an interface as a contract between the designer of the class and the caller of the class. The interface determines what public fields and methods are visible to a caller of a class. C# provides direct support for "design by contract" with the key word interface. In C#, a class can inherit multiple interfaces and a single implementation hierarchy. Thus a class can contain one or more distinct public contracts. Both Booch and Meyer allude to the fact that types allow the compiler to enforce design decisions and influence the execution of software. Why is this so important? The answer is that references imply restricted access. References Have Type You will recall that methods and properties of an object have access modifiers such as public, protected and private. The calling context and access modifiers determine the visibility of fields and methods of an object. Thus, public fields and methods are visible to callers outside of the class. However, there is another level of access control that is much more difficult to grasp and explain. In a nutshell, when you declare a reference variable, the type of the reference variable restricts access to one of the object's public contracts. You use a reference variable to touch an object's fields and properties. The key concept is that the type of the reference variable determines which of the objects public contracts (interfaces) is accessible using the reference variable. If an object had only one distinct public contract, this discussion would be moot. But in fact an object can have many public contracts. For instance, every object in the C# framework derives from the base class Object. Lets look again at the inheritance hierarchy for TextBox:

System.Object System.Web.UI.Control System.Web.UI.WebControls.WebControl System.Web.UI.WebControls.TextBox

The TextBox control inherits from WebControl which inherits from Control which inherits from Object. Each of these four classes defines an interface or public view, a type. If you declare a reference variable of type Object, only the public members defined in System.Object are visible using the reference variable.

object tb= new TextBox();


If you use the Visual Studio IDE and enter "tb." the IDE will automatically display the only four methods that can be touched using "tb": Equals() GetHashCode() GetType() ToString() Thus the type of the reference variable "tb", object, limits access to a subset of the public methods and fields of the instance of class TextBox. Only one of the many public interfaces can be touched with the reference variable "tb". You could also declare "tb" as type Control:

Control tb= new TextBox();


Now if you enter "tb.", a larger number of public fields and methods are automatically displayed by the IDE including:

Equals() GetHashCode() GetType() ToString() ... DataBind() Dispose()


Finally, if you declare a reference variable of type TextBox all of the public fields and members of the class TextBox are visible using the reference variable "tb" including:

Equals() GetHashCode() GetType() ToString() DataBind() Dispose() ... Text


All I can suggest is try it! Declare the variable "tb" using different types and see how the type of the reference variable restricts access to the public interface of the object. Note that an object's set of possible interfaces (types) can be defined by the objects class hierarchy as in the preceding example or through inheritance of multiple interfaces. For example, here is the declaration of the class Hashtable that implements six distinct interfaces:

public class Hashtable : IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback, ICloneable IEnumerable hash=new Hashtable();

The reference variable hash is of type IEnumerable and is restricted to the public methods and fields of the IEnumerable Interface and System.Object:

Equals() GetHashCode() GetType() ToString() GetEnumerator()


Objects Have Class Well this should be pretty self explanatory. Remember, an object is an instance of a class and goes on the heap. A local reference variable goes on the stack and is used to touch an object. The full interface of the object is defined in the class so an object has class. The object variable, on the other hand, is restricted by its type and can only be used to touch fields and properties defined in its type (or in System.Object). The compiler enforces the design decisions. Be clear, when you created a reference variable of type object in the previous example, you still created an instance of class TextBox on the heap.

object tb= new TextBox();


This line of code creates a local reference variable of type object on the stack and an object of class TextBox on the heap. Casting About Since you can only touch an object using a reference variable, at times the need arises to change the type of a reference variable. You can do this by "casting" the type of a reference variable to another valid type. The type of the variable must be in the domain of types (public interfaces) defined by the class of the object. If you try to cast an object variable to a type that is not supported by the class of the object, a runtime exception will be thrown. "Casting up" the class hierarchy from a subtype to a base type is always safe. The converse is not true. "Casting down" the class hierarchy is not always safe and result in a runtime InvalidCastException. Here is an example of casting down the class hierarchy:

object tb= new TextBox(); ((TextBox)tb).Text= "Hello";


By explicitly casting the reference variable to the type TextBox, you are telling the compiler that you want to access the full interface of the class TextBox. A more common task is create another reference variable like this:

TextBox textBox= (TextBox)tb;


This creates a separate local reference variable on the stack of type TextBox. Both variables, "tb" and "textBox", contain references to the same object on the heap of class TextBox, but each variable has a different type and hence different access to the public fields and methods of the single object on the heap. A Twisted Analogy Now if this is just not making sense to you, let me try a twisted analogy of types. Just as an object can have different public views, a complex person can wear different "hats" or play different roles in life. A complex person can have multiple defined roles or types. When a complex person is wearing the "hat" of say a police officer, he or she is restricted by the implied

contract between the clients (the populace) and the role of a police officer. When in uniform, the complex person has a type of police officer. When that same complex person goes home, he or she may put on the "hat" of a parent and is expected to exhibit behavior consistent with the role of a parent. At home, off duty, the complex person is expected to have the type of a parent. In an emergency, the off duty complex person is expected to assume the role of a police officer. You can "cast" an off duty officer of type parent to a police officer. You should not cast a twisted programmer of type parent to the type police officer. This will definitely result in a runtime exception! IS and AS Since casting down the class hierarchy is not "safe", you must code defensively. The C# language provides the key words is and as which greatly simplifies writing exception safe code. The key word is returns true if the object referred to by the left sided operand supports the type of the right sided operand. According to the IDE: The is operator is used to check whether the run-time type of an object is compatible with a given type. The is operator is used in an expression of the form:

expression is type
Where: expression An expression of a reference type. type A type. Remarks An is expression evaluates to true if both of the following conditions are met:

expression is not null. expression can be cast to type. That is, a cast expression of the form (type) (expression) will complete without throwing an exception. For more information, see 7.6.6 Cast expressions .

A compile-time warning will be issued if the expression expression is type is known to always be true or always be false. The is operator cannot be overloaded. Here is an example using is:

private TextBox Cast(object o) { if (o is TextBox) { return (TextBox)o; } else { return null; }

} object tb= new TextBox(); TextBox textBox= Cast(tb);


In this sample using is, if the cast is invalid the result is null. Alternatively, you can use the key word as. According to the IDE: The as operator is used to perform conversions between compatible types. The as operator is used in an expression of the form:

expression as type
where: expression An expression of a reference type. type A reference type. Remarks The as operator is like a cast except that it yields null on conversion failure instead of raising an exception. More formally, an expression of the form:

expression as type
is equivalent to:

expression is type ? (type)expression : (type)null


except that expression is evaluated only once. As in the previous example using is, if the cast is not valid, the result is null. I prefer using is. I would argue that code using is, is more readable than code using as. Well I hope this discussion of references, types, classes and objects has clarified things for you. In a nutshell, when you declare a reference variable, the type of the reference variable restricts access to one of the object's public contracts. When in doubt, repeat the mantra "Objects have class, references have type."

To Inherit or Contain? That is the Question.


In Chapter 2, you visited the design conundrum of using inheritance or containment. In this chapter you will use both. First you will use inheritance to create a custom, type safe, null safe collection. You will then use containment to wrap the custom collection and "adapt" the read/write collection interface to a read only interface. Here again is the discussion from Chapter 2: One difficult design decision is to decide if a class should inherit from a parent class or hold a reference to a new object. Inheritance represents an IS_A relationship from a generalization to a specialization. Containment represents a HAS_A relationship between the whole and a part. So a car IS_A motorized vehicle, but HAS_A radio. The two relationships can be expressed in code thusly:

class Radio { ... } class Vehicle { ... } class Car : Vehicle { Radio r= new Radio(); }
Let's Get Your Inheritance One common real world task is to create a type safe, null safe collection. For instance, you might want to create a collection that can only store elements that are non null references of type Drawable. This allows you to iterate over the collection casting each element and then calling a public method on every element without fear of a NullReferenceException or a InvalidCastException. Here again is the Drawable type implemented as an interface:

// an interface version of Drawable interface Drawable { void DrawYourself(); } class Circle : Drawable { public void DrawYourself() { System.Console.WriteLine("Circle"); } } class Square : Drawable { public void DrawYourself() { System.Console.WriteLine("Square"); } }
You can now create a type safe, null safe collection by extending the abstract base class System.Collections.CollectionBase. CollectionBase was designed for use as a base class of a custom type safe collection. Extending CollectionBase automatically exposes all of the public methods of CollectionBase such as Count and GetEnumerator(). Here is an example of using inheritance to create a type safe, null safe collection of Drawable elements. The set indexer calls the type and null safe Insert method.. Note: You could also create a type safe collection by creating a class that contains an ArrayList and provides pass through getter and setter methods that take and return only references of type Drawable. This would require that you provide a do nothing pass through method for every public type safe method in ArrayList that you want to expose in the containing class.

/// <summary> /// DrawableCollection /// A type safe, null safe collection of Drawable objects /// Demonstrates the use of Inheritance /// A DrawableCollection IS_A Collection /// Extends CollectionBase to create a specialization /// </summary> class DrawableCollection : System.Collections.CollectionBase { // Custom implementations of the protected members of IList // returns -1 if parameter is null public int Add(Drawable value) { if (value != null) { // throws NotSupportedException return List.Add(value); } else { return -1; } } public void Insert(int index, Drawable value) { if (value != null) { //throws ArgumentOutOfRangeException List.Insert(index, value); } // else do nothing } public void CopyTo(Array array, int start) { //throws ArgumentOutOfRangeException List.CopyTo(array, start); } // provide an indexer public Drawable this[int index] { get { // ArgumentOutOfRangeException return (Drawable)List[index]; } set { //throws ArgumentOutOfRangeException Insert(index,value); } } }
The key here is that all of the setter methods (Add, Insert, set) validate for non null and take a reference of type Drawable. Any attempt to pass a null reference will be ignored. Any attempt to pass a reference to an object that does not support the Drawable interface will fail. This guarantees that all elements in the collection are of the type Drawable and are not null. This

allows you to iterate over the collection without fear of a NullReferenceException or a InvalidCastException like this:

foreach(Drawable d in drawableCollection) { System.Console.WriteLine(d.ToString()); }


Note: Using foreach hides the call to GetEnumerator(). Here is the explicit call using IEnumerator:

System.Collections.IEnumerator enumerator= dc.GetEnumerator(); while (enumerator.MoveNext()) { System.Console.WriteLine(((Drawable) (enumerator.Current)).ToString()); }


C# supports the concept of an indexer which supports random access to a collection using the index operator ([]). A custom indexer does not add support for a Length property. Here again is the get and set code that creates an indexer:

// provide an indexer public Drawable this[int index] { get { // throws ArgumentOutOfRangeException return (Drawable)List[index]; } set { //throws ArgumentOutOfRangeException Insert(index,value); } }
You can then use the indexer like this:

// create a DrawableCollection DrawableCollection dc= new DrawableCollection(); dc.Add(new Circle()); // test indexer Drawable draw= (Drawable)dc[0];
A Better Class Hierarchy Although the type safe, null safe collection above works, you could improve the class design by first creating a null safe collection. The following class simply insures that null objects cannot be inserted into the collection. Note that all of the setters are declared protected as this class was designed to be extended, not instantiated.

// A null safe collection. This class is meant to be // extended by a type safe class so that the setter // methods are protected.

class NullSafeCollection : System.Collections.CollectionBase { // class is not meant to be instantiated, only inherited protected NullSafeCollection(){} // Custom implementations of the protected members of IList // These methods are for internal use by a type safe subclass // returns -1 if parameter is null protected int Add(object value) { if (value != null) { // throws NotSupportedException return List.Add(value); } else { return -1; } } protected void Insert(int index, object value) { if (value != null) { //throws ArgumentOutOfRangeException List.Insert(index, value); } // else do nothing } // provide an indexer protected object this[int index] { get { //throws ArgumentOutOfRangeException return List[index]; } set { //throws ArgumentOutOfRangeException Insert(index,value); } } // expose single public method, get only CopyTo public void CopyTo(Array array, int start) { //throws ArgumentOutOfRangeException List.CopyTo(array, start); }

You can now extend from this null safe collection, creating a type safe and null safe collection of Drawable elements. The advantage of this design hierarchy is that you can now reuse the NullSafeCollection class to create a different type safe collection class. Here is the final type safe, null safe class:

class DrawableCollection : NullSafeCollection { // Custom implementations of the protected members of IList // returns -1 if parameter is null public int Add(Drawable value) { return base.Add(value); } public void Insert(int index, Drawable value) { base.Insert(index, value); } // provide an indexer public new Drawable this[int index] { get { //throws ArgumentOutOfRangeException return (Drawable)base[index]; } set { //throws ArgumentOutOfRangeException base.Insert(index,value); } } }
Note the key word new which tells the the compiler that you are explicitly shadowing or hiding the indexer in the base class. You cannot override the base indexer since the subclass has a different return type than the base class. Wrap It Up Please (Using Containment) Another common task is to pass a "read only" reference to a caller. (This restriction is available in C++ using the key word const on a pointer in the method parameter list declaration. Using const on a pointer prevents corruption of any data that can be touched with the pointer within the method.) One way to pass a "read only" reference to a collection in C# is to "wrap" a reference in another object. This is an example of using containment. As I view it, the read/write interface of the DrawableCollection is "adapted" to a read only interface. When you adapt an existing interface to a new interface, you are using the Adapter Design Pattern. Wrapping or adapting a class is a common idiom. (For instance, you might want to wrap an unmanaged legacy Win32 dll function in a managed C# class.) Here is a read only class WrapCollection that contains a private reference to a DrawableCollection.

/// <summary> /// WrapCollection /// Demonstrates wrapping our DrawableCollection to limit access /// Demonstrates the use of Containment /// WrapCollection contains, HAS_A, DrawableCollection /// Adapts the read write interface to a read only interface /// Demonstrates the Adapter Design Pattern /// </summary> class WrapCollection

private DrawableCollection collection; // constructor public WrapCollection(DrawableCollection collection) { if (collection != null) { // reference to an existing collection this.collection= collection; } else { // new empty collection this.collection= new DrawableCollection(); } } // provide a get only indexer // throws ArgumentOutOfRange if collection is empty public Drawable this[int index] { get { // throws ArgumentOutOfRangeException return (Drawable)collection[index]; } } public System.Collections.IEnumerator GetEnumerator() { return collection.GetEnumerator(); } public int Count { get { return collection.Count; } }

The key here is to declare the reference variable collection as private. Declaring collection private, prevents the public user of the WrapCollection object from accessing any of the setters in the contained DrawableCollection.

private DrawableCollection collection;


Note the design decision to create a new empty DrawableCollection if the caller passes null to the WrapCollection constructor. This design allows the caller to blissfully iterate over the contained collection using IEnumerator or foreach without throwing a runtime exception.

// constructor public WrapCollection(DrawableCollection collection) { if (collection != null) { this.collection= collection; }

else { } }
If the user passes null to the WrapCollection constructor, the calls to GetEnumerator() and Count will still be valid, returning an empty enumeration and a count of zero. Test It! Go ahead. Compile the DrawableCollection and WrapCollection. Then use the following code to test the type safe, null safe collection. Passing a WrapCollection prevents the caller from modifying the contained collection since the collection is not visible outside of the class.

this.collection= new DrawableCollection();

class Test { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // // create a DrawableCollection DrawableCollection dc= new DrawableCollection(); dc.Add(new Circle()); dc.Add(new Circle()); dc.Add(null); dc.Add(new Square()); dc.Insert(1,new Square()); // test indexer Drawable draw= (Drawable)dc[0]; System.Console.WriteLine(draw.ToString()); // dc[0]= null; // no action // dc[0]= "Hello"; // fails at compile time // test Count int num= dc.Count; System.Console.WriteLine(num.ToString()); // test CopyTo Drawable[] copy= new Drawable[num]; dc.CopyTo(copy,0); foreach(Drawable d in copy) { System.Console.WriteLine(d.ToString()); } // test IEnumerator foreach(Drawable d in dc) { System.Console.WriteLine(d.ToString()); } // Create a WrapCollection WrapCollection wrap= new WrapCollection(dc); // try this instead!

} }

// WrapCollection wrap= new WrapCollection(null); // test Count int count= wrap.Count; System.Console.WriteLine(count.ToString()); // test indexer if (count > 0) { System.Console.WriteLine(wrap[0].ToString()); } // test IEnumerator foreach(Drawable d in wrap) { System.Console.WriteLine(d.ToString()); } System.Console.ReadLine();

Be careful, the code can still throw an ArgumentOutOfRangeException. Well, I hope you have a better feel for inheritance and containment!

Shadow Fields, Override Virtual Methods


Well, I am going to finish this "nuts and bolts" chapter before I flame out! I promised that I would discuss overriding, so I am going to make good on this promise. In general when you extend a class, you shadow fields with the same name in the base class and override virtual methods with the same name and parameter list in the base class. Overriding makes the base class method invisible. Shadowing a field, only hides the field from view. You can still explicitly touch the hidden shadowed field if you wish. You cannot touch an invisible overridden method. To demonstrate the difference between shadowing and overriding I resort, as usual, to twisted code! First, you can create a sample base class with a public read only field "toastTime" and a virtual method "MakeToast()":

class Base { public readonly int toastTime= 60; public virtual void MakeToast() { System.Console.WriteLine("MakeToastInSeconds: " + toastTime.ToString()); } }
Declaring the only method virtual explicitly allows a designer to override the MakeToast() method in a subclass. (Contrast this to the approach in Java in which all methods are virtual by default.) This is important, since you are explicitly allowing a subclass to completely rewrite the implementation of the MakeToast() method and in doing so make it totally invisible! Shadow Fields, Override Methods in the Base Class Now you can extend or subclass the class Base:

/// <summary> /// Summary description for SubClass /// </summary> class SubClass : Base { public readonly new int toastTime= 1; public override void MakeToast() { System.Console.WriteLine("MakeToastInMinutes:" + toastTime.ToString()); } }
Note: You must explicitly tell the compiler that you are overriding the virtual base class method MakeToast() with the key word override and that you are hiding the base field with the key word new. (You cannot override a field in a base class.) Overriding the method MakeToast makes the base class method with the same name and signature invisible to the caller of the class. This is in contrast to the base class field toastTime. The base class field toastTime is shadowed, but still potentially visible to the caller. You have shadowed a base class field and overridden a base class method. You can demonstrate the behavior of shadowed fields with the following test code:

SubClass sc= new SubClass(); System.Console.WriteLine(sc.toastTime.ToString()); // --> 1 Base super= (Base)sc; System.Console.WriteLine(super.toastTime.ToString()); // --> 60
In the above code snippet, the type of the reference variable determines which value of toastTime can be touched with the reference variable. Touching the field with a reference of type SubClass tells the compiler that you want to touch the the toastTime field of class SubClass. Casting the reference variable to the base type, tells the compiler that you want to touch the toastTime field of the type Base. Both fields are potentially visible to the caller. The base class field is shadowed, but still touchable. You can demonstrate the behavior of an overridden method with the following test code. This code demonstrates that the overridden base class method MakeToast is invisible. You cannot touch the overridden method even if you cast the reference to the base type.

SubClass sc= new SubClass(); sc.MakeToast(); // --> MakeToastInMinutes: 1 Base super= (Base)sc; super.MakeToast(); // --> MakeToastInMinutes: 1
Despite the cast, only the derived (specialized) class method is visible. If you think about it, this behavior is absolutely essential to polymorphism. Overriding insures that the "proper" implementation of a polymorphic method is called at runtime. You can demonstrate the proper polymorphic behavior with a little sample code. Here is yet another version of the Drawable class, now with a default implementation of DrawYourself.

class Drawable { public virtual void DrawYourself() {

System.Console.WriteLine("Drawable");

} class Square : Drawable { public override void DrawYourself() { System.Console.WriteLine("Square"); } } class Circle : Drawable { public override void DrawYourself() { System.Console.WriteLine("Circle"); } }
Here is the sample code that demonstrates that the "proper" implementation is called at runtime.

Drawable draw= new Drawable(); draw.DrawYourself(); //--> Drawable draw= new Square(); draw.DrawYourself(); //--> Square draw= new Circle(); draw.DrawYourself(); //--> Circle
Overriding insures that the proper super class implementation is always called at runtime. The magic of polymorphism is secure. You Can Hide a Method For completeness sake, I will mention that you can hide a virtual method using the key word new instead of the key word override. Go ahead. Edit the previous code sample and replace the key word override with the key word new. This is the new behavior that breaks polymorphism:

Drawable draw= new Drawable(); draw.DrawYourself(); //--> Drawable draw= new Square(); draw.DrawYourself(); //--> Drawable draw= new Circle(); draw.DrawYourself(); //--> Drawable
Perhaps not what you wanted!

Interfaces
Although I danced around this subject in the tutorial, I never explicitly tried to explain an interface. C# has a key work interface which allows you to describe a contract without any implementation. An interface can contain zero or more abstract methods. You cannot create an instance of an interface.

As I suggested in the tutorial, an interface is similar to a pure virtual class in C++. It describes a set of method signatures, but does not provide any implementation details. A Twisted Analogy If a class is a blueprint from which you can create zero or more objects in memory, then you may ask what is an interface? Well, I have struggled here for a good analogy. You can think of an interface as one of many possible abstract contracts between the builder of a custom building and the client. If you are building tract homes, then you can simply use the stock blueprint, modifying the usual properties such as color. If you are going to build a custom rendition of a home using a blueprint, then the builder and client will need come to verbal contracts about the building. These preliminary verbal contracts do not describe the actual physical details of how the building will be constructed or embellished, but simply codifies an understanding between the principals, the designer/builder and the client. The verbal contract describes what the client wants, but not the gory details on how the goal will be implemented. One verbal agreement might be that building will be be wired for cable TV. Another agreement might be that there will be a home theater addition to the house. The designer/builder and client must then agree on an implementation of the abstract contracts before proceeding with construction. Your construction project inherits from the blueprint and the designer/builder implements zero or more custom design decisions. Thus, in the land of C#, a construction project (concrete class) can inherit from a single blueprint and implement zero or more contracts. More importantly, every building in the land of C# is constructed with absolute precision! Cool! Sample Code: Pure Abstract Class vs. Interface The general syntax for a pure abstract class and interface is:

abstract class MyAbstractClass { public abstract someType MyMethod(...); ... } interface MyInterface { someType MyMethod(...); ... }
Not surprisingly, the syntax for inheriting from a class or implementing an interface is the same:

class MyClass : MyAbstractClass, MyInterface ... { ... }


Here again is our pure abstract Drawable class from Chapter 4:

abstract class Drawable { public abstract String DrawYourself(); } class Circle : Drawable { public override String DrawYourself() {

return "Circle";

} class Square : Drawable { public override String DrawYourself() { return "Square"; } }


Since the base class Drawable does not contain any implementation details, it can be rewritten as an interface. Here is a slightly different version of the Drawable type implemented as an interface from Chapter 7:

// an interface version of Drawable interface Drawable { void DrawYourself(); } class Circle : Drawable { public void DrawYourself() { System.Console.WriteLine("Circle"); } } class Square : Drawable { public void DrawYourself() { System.Console.WriteLine("Square"); } }
If you try to create an instance of the Drawable interface, the compiler will complain:

Cannot create an instance of the abstract class or interface 'TestInterface.Drawable'


In general, if you are designing a contract without any implementation details, then you should use an interface. Use an abstract class if you want to include some implementation details. Remember, your class can only inherit from one class hierarchy, but can implement multiple interfaces. If you accept that interfaces in C# are analogous to pure virtual classes in C++ then, in essence, C# supports single inheritance of implementation and multiple inheritance of interface.

Vous aimerez peut-être aussi