TweetFollow Us on Twitter

A Primer on the C# Programming Language (Part One)

Volume Number: 20 (2004)
Issue Number: 3
Column Tag: Programming

Casting Your .NET

by Andrew Troelsen

A Primer on the C# Programming Language (Part One)

Exploring .NET development on Mac OS X

Topic Prelude

If you have read the previous installments of this series (except last month when I missed the deadline), you should be well aware that the .NET platform is language agnostic. While this is technically correct, I'd be lying if I did not admit that C# is currently the language of choice for a majority of .NET developers. Given this fact, my goal in the next two issues is to offer a tour of the major syntactical features provided by C#. Understand of course, that two articles cannot possibly examine each and every token and construct of a given language. In any case, once you have digested the material presented here, you should feel quite comfy with the core aspects of C# and be in a perfect position to follow along with the articles to come.

Recall the Pillars of OOP

All object languages must contend with the three 'pillars of object oriented programming' (OOP). First, an OOL (object oriented language) must address the concept of encapsulation. Simply put, encapsulation services provide a way for types to safely control access to their private data points. Next we have inheritance, which provides a manner in which exiting types may be reused and extended. Last but not least we have the third pillar of OOP termed polymorphism. This pillar of OOP allows related types to respond uniquely to the same method invocation. Given that C# is a modern OOL, you are correct to assume that C# provides complete support for the pillars of OOP, as well as a relatively new paradigm termed aspect oriented programming (AOP) which will be examined in a later article. Before we dig into the details of OOP using C#, let's check out basics of defining classes and allocating objects.

Defining Class Types in C#

Classes are the cornerstones of any OOL, in that they provide a template for the objects that comprise your application. In C#, class types are defined using (not surprisingly) the 'class' keyword. Like other languages in the C family, C# classes may support any number of overloaded constructors to allow an object to come to life in a particular state. To illustrate, assume we have a class named Car (defined in a file named car.cs), which defines three pieces of private data to represent a given automobile's pet name, current speed and make (Listing 1).

Listing 1. A simple C# class definition (car.cs).

using System;
namespace CSharpOOPExample
{
     // The Car class type. 
  public class Car  
  {
          // State data (could be defined as protected if desired).
    private string petName;
    private int currSpeed;
    private string make;
          // Constructor set.
    public Car(){}
    public Car(string pn, int cs, string m)
    {
      petName = pn; currSpeed = cs;
      make = m;
    }
          // Override the virtual method System.Object.ToString()
          // in order to display our state data.
    public override string ToString()
    {
      return string.Format(
        "Name: {0}; Speed: {1}; Make: {2}", petName,
        currSpeed, make);
    }  
  }
}

The first point of interest has to do with the 'public' keyword used when defining the type. In C#, a non-nested type may be defined as public or 'internal' (the default). The distinction is made clear when you recall that types are contained within an assembly. Public types may be created and manipulated across assembly boundaries. On the other hand, internal types can only be created and used by the assembly that defines it. Thus, if you were to build a .NET assembly which contained three public types and two internal types, other assemblies would be completely unaware of the two internal types. Using this technique, assembly builders are free to define any number of internal helper types that are invisible to other binary units.

Next, you can see that we have defined a method named ToString() using the C# 'override' keyword. This brings up a very important point regarding the .NET platform: If you do not say otherwise, class types automatically derived form the cosmic base class, System.Object (introduced in the October 2003 installment of Casting your .NET). Like many base classes, Object defines a set of virtual methods that may be redefined (which is to say, overridden) by derived classes. Here, the virtual System.Object.ToString() method has been overridden in order to return a custom blurb of text which represents the current state of a given Car type (the default implementation of ToString() returns the type's fully qualified name). We'll examine the details of virtual members and member overriding a bit later in this article.

Finally, note that the Car class has two constructors. The role of our custom constructor is clear enough, in that it allows the object user to create a car in an initial state. The other constructor may seem a bit odd (depending on your exposure to other C based languages) in that it's implementation does nothing at all. C#, like Java and C++ always supply a freebee no-argument constructor (termed the default constructor) for each and every class definition. However, as soon as you define a custom constructor, the default, default constructor (pardon the redundancy) is removed. Therefore, if you with to allow objects of this type to be created with no arguments, you must redefine the no-argument constructor.

On a final constructor-related note, recall the C# automatically sets a type's state data to safe default values (quite unlike C++). The rules are quite simple:

  • Numerical data is set to 0 or 0.0.

  • Object references are set to null.

  • Booleans are set to false.

Given this language feature, we have no need to assign values to petName, currSpeed or make within the scope of the default constructor.

Allocating and (indirectly) Destroying Objects

We are now ready to create an application object (e.g., the class defining the Main() method) to allocate an auto or two onto the managed heap (Listing 2).

Listing 2. Creating Cars (carApp.cs).

using System;
namespace CSharpOOPExample
{
      // The App object. 
  internal class CarApplication
  {
          // Program's entry point
    private static void Main()
    {
               // Make some Cars!
      Car noName = new Car();
      Console.WriteLine(noName.ToString());
      Car someCar = new Car("Zippy", 90, "BMW");
               // ToString() called automatically.
      Console.WriteLine(someCar); 
    }  
  }
}

In C#, the 'new' keyword is used to allocate an instance of a given class type onto a region of memory termed the managed heap (in fact, class types can only be heap allocated. Stack allocated data is achieved through the use of value types, as described in the next issue). In a similar fashion as the Java platform, .NET provides a garbage collector that is in charge of destroying unused objects when required. Given this, C# does not provide a corresponding keyword (such as 'delete') to explicitly destroy an object. However, C# does provide a syntax which looks suspiciously close to a C++ style destructor. Ponder the following updated Car type (Listing 3):

Listing 3. C# style 'destructors'.

// The updated Car class type 
public class Car
{
  ...
  ~Car()
  {
    Console.WriteLine("This car is destroyed.");
  }  
}

Like C++, C# destructors are syntactically denoted using a tilde prefix, however the similarities end here. First and foremost, a C# destructor is in reality a short hand notation for overriding the virtual System.Object.Finalize() method (to verify this for yourself, run your assembly through ildasm and check out how C# destructors are expressed in terms of CIL code). Next, remember that C++ memory management is quite deterministic in nature, in that we programmers are the individuals responsible for destroying heap allocated memory. In contrast, the .NET platform uses a non-deterministic finalization approach. In other words, you do not know exactly when the garbage collector will remove an object from the heap, only that the associated memory will eventually be reclaimed. When the object is indeed destroyed, the .NET runtime will ensure that your type's destructor is invoked if present.

As you might guess, there is much more that could be said about the .NET garbage collection process (such as programmatically controlling garbage collection using System.GC, implementing the IDisposable interface, object generations, etc), however the current explanation will suffice for now.

Encapsulation Support via Type Properties

Our current iteration of the Car type is dysfunctional to say the least, as we have not provided a way to get or set the state data after the time of construction! .NET programming languages prefer the use of type properties, rather than traditional getters and setters to honor the pillar of encapsulation. In the February 2004 issue you examined property syntax via JScript.NET, and will be happy to know that the act of defining properties in C# is quite similar. Listing 4 illustrates how to preserve encapsulation of the private petName member variable using a public property named Name (assume that the make and currSpeed member variables are encapsulated by additional properties; Make and Speed respectively).

Listing 4. C# property syntax.

public class Car
{
  private string petName;
...
     // C# Property syntax.
  public string Name
  {
    get { return petName; }
    set { petName = value; }
  }
}

Recall that the name of a property does not need to have any relationship to the name of the data point it is responsible for exposing. Also note the use of the 'value' token in the implementation of the property set scope. Truth be told, 'value' is not really a true-blue keyword in the C# programming language given that it is legal to define member variables or local variables named 'value'. However when this token appears in the context of a property setter, it is used to represent the incoming value assignment. Finally, it is worth noting that properties can be configured as read-only or write-only. Simply omit the get or set scope from the property definition.

For testing purposes, update your Main() method to change and obtain various data points (Listing 5).

Listing 5. Exercising our properties.

internal class CarApplication
{
  // Program's entry point
  private static void Main()
  {
    ...
    Car someCar = new Car("Zippy", 90, "BMW");
    someCar.Name = "Junior";
    Console.WriteLine("{0} is going {1} MPH.", 
      someCar.Name, someCar.Speed); 
  }  
}

At this point you can compile your C# files into an executable assembly (don't forget to enable an SSCLI-aware Terminal). The commands listed in Listing 6 will do the job nicely.

Listing 6. Compiling and executing our Car application.

DoSscli
csc *.cs
clix carApp.exe

Next up, we will examine how to build a set of related types using classic inheritance.

The Syntax of Inheritance

As mentioned, if you build a class type that does not explicitly specify a base class, your type will automatically derive from System.Object. However, when you wish to build class hierarchies you will no doubt be interested in deriving new types from existing class definitions. This is accomplished in C# using the colon operator. Let's create three child classes (SportsCar, MiniVan and JamesBondCar) that leverage our current Car type (assume each of these new types are within a file named childCars.cs and are wrapped within the CSharpOOPExample namespace). Listing 7 defines the SportsCar type.

Listing 7. The SportsCar class type (childCars.cs).

// SportsCar IS-A Car.
public class SportsCar : Car
{
  public SportsCar(string pn, int cs, string m)
    : base(pn, cs, m) {}    
  public SportsCar(){}
  public void TurboBoost()
  { Speed =+ 20; }
}

Beyond the fact that SportsCar is explicitly deriving from the Car type (and therefore inherits each of the public and protected members of it's base class), observe the use of the 'base' keyword in the custom constructor. As you can see, 'base' is dangling off the constructor definition by way of a single colon (which in this case is not marking the name of the base class). When the base keyword is used in this manner, you are specifying which constructor to call on the parent class when the derived type is created. Given that Car already has storage for the petName, currSpeed and make data points, we are explicitly calling the three-argument constructor of the parent. If we did not do so, the parent's default constructor would be called automatically, forcing us to set the private data points using the inherited public properties or possibly protected data (which is obviously less efficient).

As well, notice the implementation of the TurboBoost() method. Another bonus of property syntax is that they respond to the intrinsic operators of C#. Thus, rather than having to increase the SportsCar's speed using traditional accessor and mutator logic (Listing 8) we can use the more streamlined code "Speed += 20;".

Listing 8. Properties streamline traditional get / set logic.

// If we were not using properties...
public void TurboBoost()
{
  setSpeed(getSpeed() + 20);
}

Listing 9 details the MiniVan type, who's first point of interest is that the custom constructor passes three of the four incoming arguments to the base class, while assigning the fourth and final parameter to it's own custom point of data (numberOfKids). Also notice how MiniVan overrides the parent's implementation of ToString() to account for it's custom piece of state data. In this case, the 'base' keyword is not triggering a base class constructor using the 'dangling colon on the constructor' syntax, but simply calling a base class method within the scope of the method definition.

Listing 9. The MiniVan class type (childCars.cs).

// MiniVan IS-A Car.
public class MiniVan : Car
{
  public MiniVan(string pn, int cs, 
    string m, int k)
    : base(pn, cs, m) 
  {
    numberOfKids = k;
  }
  public MiniVan(){}
  
  private int numberOfKids;  
  public int KidCount
  {
    get {return numberOfKids;}
    set { numberOfKids = value;}
  }
    
  public override string ToString()
  {
    return string.Format("{0}; kids: {1}",
      base.ToString(), numberOfKids);
  }
}   

Finally, Listing 10 illustrates the final automobile, JamesBondCar. Note that JamesBondCar extends SportsCar, which in turn extends Car (which extends System.Object).

Listing 10. The JamesBondCar class type (childCars.cs).

// JamesBondCar IS-A SportsCar
// which IS-A Car.
public class JamesBondCar : SportsCar
{
  public JamesBondCar(string pn, int cs, string m)
    : base(pn, cs, m) {}
  public JamesBondCar(){}
  public void DiveUnderWater()
  { Console.WriteLine("Diving under water!");}
  public void Fly()
  { Console.WriteLine("Taking off into the air!");}
}   

Needless to say, our JamesBondCar is able to dive under water and fly into the air to escape the current enemy at hand. Further, given that this type does not add any new member variables to the mix, the parent's ToString() implementation will fit the bill nicely.

Building a Array of Car types

At this point the Main() method may be updated to exercise each of these new derived classes. To provide a more interesting example however, let's create an array of Car types. As you are most likely aware, most OOLs (including Java and C++) allow you to store a derived object in a base class reference (e.g., and implicit cast). This is legal given the 'IS-A' relationship enforced by classical inheritance. Given this fact, update Main() to create an array of Car-compatible types and iterate over the array using the C# 'foreach' keyword to invoke each object's ToString() implementation (Listing 11).

Listing 11. Creating an array of Car-compatible types.

// Make an array of Car types.
Car[] allTheCars = new Car[3]
 { new SportsCar("Zippy", 85, "Audi TT"),
   new MiniVan("KidMobile", 55, "Caravan", 10),
   new JamesBondCar("QMobile", 120, "*Classified*")};
   
// Print out the number of cars in array.
Console.WriteLine("You have {0} cars:", 
  allTheCars.Length);    
  
// Call each auto's ToString() method. 
foreach(Car c in allTheCars)
 Console.WriteLine(c.ToString());

A few points of interest. In C#, arrays are declared using the C-like square bracket notation. Here we have created an array of Car types named allTheCars. The 'new' keyword used when declaring the array is not creating any particular Car type, but rather the underlying System.Array in the background. Given that C# arrays always derive from the System.Array base class, each array has access to each of the public members (such as the Length property seen in the previous code segment).

Once we have allocated a System.Array capable of holding Car-compatible types, we can leverage the curly-bracket shorthand notation to fill the array with sub-elements at the time of creation. If you would rather, you are free to allocate and initialize an array on an item-by-item basis (Listing 12).

Listing 12. Creating an array of Car-compatible types (the long way).

// Long hand array creation. 
Car[] allTheCars = new Car[3];
allTheCars[0] = new SportsCar("Zippy", 85, "Audi TT");
allTheCars[1] = 
  new MiniVan("KidMobile", 55, "Caravan", 10);
allTheCars[2] = 
  new JamesBondCar("QMobile", 120, "*Classified*");

The Details of C#'s 'foreach' Keyword

Speaking of System.Array, if you were to look up the formal definition of System.Array using any of the tools that ship with the SSCLI (see Feb 2004) you will find that this class type implements an interface named System.Collections.IEnumerable. System.Collections.IEnumerable defines a single method named GetEnumerator(), which returns yet another interface named System.Collections.IEnumerator. This interface provides a way for a type to iterate over contained sub-items using three members:

  • Current : This property returns the item current 'pointed to'.

  • Reset() : This method resets the internal indexer's position to the first item.

  • MoveNext() : As you would guess, this advances in the internal indexer by one. Returns false when the end of the list has been reached.

So, why do we care about IEnumerable and IEnumerator? Well, the 'foreach' keyword of C# is preprogrammed to obtain these underlying interfaces to traverse the sub-objects of the array being iterated over. Given that all of these sub-objects have a ToString() implementation, we can safely invoke each auto's custom version. Be aware that System.Array is not the only type which implements the necessary interfaces required by the foreach construct. Most of the class types found within System.Collection support similar infrastructure, and if you wish to build a strongly typed custom collection, you can implement these interfaces directly to traverse custom types using 'foreach'.

The ABCs of Polymorphism: Virtual and Abstract Members

The final pillar of OOP to examine is polymorphism, which you have already begun to leverage when you overrode the virtual System.Object.ToString() and System.Object.Finalize() methods in your custom class types. As mentioned, classical polymorphism is the trait of OOP that allows hierarchies of types to responding uniquely to the same message (a.k.a., method invocation). Polymorphism is supported in C# using four simple keywords:

Base: As already seen, 'base' allows you to trigger a parent's method / constructor.

Virtual: This keyword allows you to define a base class method that has a default implementation, but may be overridden by a child class if required.

Abstract: This keyword allows you to define an abstract base class (ABC) as well as abstract methods. Recall that abstract classes cannot be directly created, but can be used to hold references to derived types. Also recall that abstract methods do not have a default implementation, and therefore derived types must provide a concrete implementation, or define themselves as abstract classes as well.

Override: This keyword allows a derived class to redefine a virtual method as well as implement an abstract member.

To inject some polymorphic activity into our existing application, let's add an abstract method to our Car base class called PrintBumperSticker(). Be aware that when a class defines an abstract member, the class must also be marked as abstract (Listing 13).

Listing 13. The abstract Car type.

// The abstract Car class type 
public abstract class Car
{
     // All derived classes must
     // implement this member or become
     // abstract types as well. 
  public abstract void PrintBumperSticker();
...
}  

Given that Car has now been redefined as an ABC, it is a compile time error to directly create Car types. However Car (and ABCs in general) still has a very useful purpose, in that it defines all of the common functionality for derived types. Car has been further updated with a single abstract member, and therefore each and every derived class in now required to provide an implementation of this member (if you do not, you are issued compile time errors).

To rectify this issue, update SportsCar, MiniVan and JamesBondCar as you see fit using the 'override' keyword. Listing 14 shows one possible implementation for the MiniVan type.

Listing 14. MiniVan's PrintBumperSticker() implementation.

public class MiniVan : Car
{
  public override void PrintBumperSticker()
  {
    Console.WriteLine
     ("All my money and Kids go to the U of Mn.");
  }
...
}  

Runtime Type Discovery using C#

Now that we have a polymorphic interface defined by our base class, we can update our Main() method to invoke each type's custom implementation (Listing 15).

Listing 15. Polymorphism at work.

foreach(Car c in allTheCars)
{
  Console.WriteLine(c.ToString());
  c.PrintBumperSticker();
  Console.WriteLine();
}

Understand that the code within the foreach block is only legal because of the defined polymorphic interface. We can rest assured that all types have an implementation of ToString() given the fact that all classes ultimately derive from System.Object, and that all descendents of car must implement the abstract PrintBumperSticker() method. However, what if we wish to call specific members of the JamesBondCar, MiniVan or SportsCar types? If you look closely at the foreach syntax, you can see that we are using a base class reference to represent each sub-object. Therefore, the following would be a compile time error (Listing 16).

Listing 16. Can't directly access derived type members from a base class reference!

foreach(Car c in allTheCars)
{
  ...
  // Nope! Car does not define a KidCount
  // property! Compiler error!
  int numberOfKids = c.KidCount;  
} 

When you need to dynamically discover if a given type is comparable with a given base class (or interface), C# provides two keywords. Ponder the following update (Listing 17).

Listing 17. Runtime type discovery in C#

foreach(Car c in allTheCars)
{
  Console.WriteLine(c.ToString());
  c.PrintBumperSticker();
      
  // Is 'c' a JamesBondCar?
  if(c is JamesBondCar)
    ((JamesBondCar)c).DiveUnderWater();
    
  // Is 'c' a MiniVan?        
  MiniVan m = c as MiniVan;
  if(m != null)
    Console.WriteLine("I have {0} screaming kids!", 
      m.KidCount);
  Console.WriteLine();
}

The 'is' keyword is quite helpful in that it returns a System.Boolean that denotes if the current object is compatible with a given base class (or interface type). If the test succeeds, you can make a safe explicit cast (using the familiar C-style casting syntax) to access the underlying functionality. The 'as' keyword is similar, however 'as' will return a null object reference if the types being tested are incompatible. Therefore, when performing a runtime check for type compatible using the 'as' keyword, be sure to test for null before casting!

On a final casting related note, you can make use of one additional construct to check for type compatibility: structured exception handing (Listing 18).

Listing 18. Manually handling an InvalidCastException.

// Is 'c' SportsCar compatible?
try{
  ((SportsCar)c).TurboBoost();
}
catch(InvalidCastException ex)
{
  Console.WriteLine("OOPS!  Not a SportsCar.");
  Console.WriteLine(ex.Message);
}

Here, we are making use of structured exception handling to attempt to cast current item pulled from the array of Car-compatible types into a SportsCar. If the cast fails, the runtime will throw a System.InvalidCastException type. Given that all exceptions derive from a common base class named System.Exception, we are free to make use of any of the inherited members to display information about the error in question (such as the Message property). See online help for complete details of System.Exception.

Interface-Based Polymorphism

Excellent! At this point you have a solid understanding of how C# contends with the mighty pillars of OOP and gained some insights into runtime type discovery, explicit casting and structured exception handling along the way. To complete this article, we will shift away from our examination of class types and examine the role of interface types (remember that .NET defines five possible types from the set {class, interface, structure, enumeration, delegate}).

Interface types, in a nutshell, are a named collection of abstract (and only abstract) members. On its own, an interface is of little use, given that you cannot create an instance of an interface variable. However, when an interface is implemented on a given class (or structure) you are able to bind a set of behaviors to the type in question. The power of interface-based programming becomes crystal clear when you understand that these types allow you to breath polymorphism into types found in different class hierarchies. Let's see a complete example.

Assume you have created some new class type modeling UFOs. Given that UFOs (presumably) are not automobiles, the UFO base type will derive directly from System.Object, whereas MotherShip extends UFO (Listing 19).

Listing 19. The UFO class types (ufos.cs).

namespace CSharpOOPExample
{
  public class UFO
  {
    public void AbductHuman()
    { Console.WriteLine("Come here Earthling...");
  }
  
  public class MotherShip : UFO
  {
    public void AbductOtherUFOs()
    { Console.WriteLine
       ("You have violated the prime directive."); }
  }
}

At this point, we have two distinct hierarchies (car-types and UFO-types). When you look at the classes defined in each category, it might strike you that UFO, MotherShip and JamesBondCar could share common behavior in that they all have the ability to become airborne. If you wish to build a further association between these types, you won't get very far with classical polymorphism given that virtual and abstract methods in an ABC are only useful if the types are in the same hierarchy (which is not the case here). However, if you pull the common functionality into an interface definition, you can selectively attach this behavior on a type-by-type basis. To illustrate, define an interface named IAirVehicle within a file named interfaces.cs (Listing 20).

Listing 20. The IAirVehicle interface (interfaces.cs)

namespace CSharpOOPExample
{
  public interface IAirVehicle
  {
    void Hover();
    bool CanLeaveAtmosphere {get;}
  }
}

Here, IAirVehicle defines a single method and a read only property. Again given that interfaces are nothing but a named collection of abstract methods, we have no implementation details, no access modifier (interface methods are always public) and no member variables.

Once an interface is defined, it may now be implemented by each type that should support this behavior. First, the UFOs (Listing 21).

Listing 21. Implementing IAirVehicle on the UFO types.

namespace CSharpOOPExample
{
  public class UFO : IAirVehicle
  {
...
    // Mark IAirVehicles.Hover() as virtual
    // to allow derived types to modify this
    // behavior. 
    public virtual void Hover()
    { Console.WriteLine
      ("Hovering and observing humans..."); }
    public bool CanLeaveAtmosphere {get {return true;} }
  }
  
  // Because MotherShip derives from UFO,
  // it is automatically IAirVehicle 
  // compatible.
  public class MotherShip : UFO
  {
...
    public override void Hover()
    { Console.WriteLine
      ("Hovering and observing other UFOs..."); }
  }
}

Implementing an interface is an all or nothing proposition. Given that UFO states that it supports IAirVehicle, it is now obligated to implement Hover() and CanLeaveAtmosphere. Notice that when UFO does implement the Hover() method, it marks this member as virtual. Thus, the derived MotherShip is free to redefine how it will implement this functionality while still being type compatible with IAirVehicle. Now, let's implement this same interface on JamesBondCar (Listing 22).

Listing 22. Implementing IAirVehicle on JamesBondCar.

public class JamesBondCar : SportsCar, IAirVehicles
{
...
  public void Hover()
  { Console.WriteLine
    ("Observing GoldFinger and OddJob..."); }
  public bool CanLeaveAtmosphere {get {return false;} }
}

Note that when you wish to explicitly mark a type's base class as well as implement some set of interfaces, you simply make use of a comma-delimited list (the first item after the semi-colon used on the class definition will always mark the base class). Given that UFO derives directly from System.Object, we can simply list the set of supported interfaces without explicitly deriving from Object (as this is assumed).

Interfaces in Action

At this point, we have three different classes (in distinct hierarchies), which implement the same interface. Now then, what is the benefit of doing so? First of all, you can declare an array of types that implement a given interface to exercise interface-based polymorphism (Listing 23).

Listing 23. Interface types as arrays.

// Create an array of IAirVehicle compatible types. 
IAirVehicle[] myFlyingObjects = new IAirVehicle[4];
myFlyingObjects[0] = 
  new JamesBondCar("Bimmer", 120, "*Classified*");
myFlyingObjects[1] = new UFO();
myFlyingObjects[2] = new UFO();
myFlyingObjects[3] = new MotherShip();
        
foreach(IAirVehicle aVCompatibleType in myFlyingObjects)
{
  Console.WriteLine("Can leave atmosphere? {0}",
    aVCompatibleType.CanLeaveAtmosphere);
}

To deepen your appreciation of interface programming techniques, assume we now which to create a System.Collections.ArrayList type within our Main() method. Because the Add() method of the ArrayList type is prototyped to take System.Objects, you can add literally anything into the container (Listing 24).

Listing 24. Populating our ArrayList with numerous things...

ArrayList allMyStuff = new ArrayList();
allMyStuff.Add(new JamesBondCar());
allMyStuff.Add(22);
allMyStuff.Add("Go Baldy, it's your birthday...");
allMyStuff.Add(new MiniVan());
allMyStuff.Add(new MotherShip());
allMyStuff.Add(false);
        
foreach(object o in allMyStuff)
{
  if(o is IAirVehicle)
    ((IAirVehicle)o).Hover();
  else
    Console.WriteLine("sorry, not an air vehicle.");
}

Here, the allMyStuff object contains numerous unrelated items (JamesBondCars, System.Int32s, System.String types, System.Booleans and so on), however we are able to investigate each sub-item using the 'is' (or 'as') keyword to dynamically discover which items are IAirVehicle compatable. If the current item is IAirVehicle aware, we cast the object accordingly and call the Hover() method. Again, the beauty of the interface is the fact that we can inject polymorphism across diverse class hierarchies. Furthermore, given the language agnostic nature of .NET, it is commonplace to define an interface in one programming language and implement it within another.

Like garbage collection, there are numerous other topics regarding interface based programming techniques under the .NET platform (explicit interface implementation, interface hierarchies, multiple inheritance of interface types and whatnot), however we'll need to call it a day for the time being.

Wrap Up

In this installment of Casting Your .NET you examined how the C# programming language contends with the pillars of OOP. Once you drilled through the basics of class definition and object allocation, you saw how to define type properties in the syntax of C#. Next you created a hierarchy of types using classical inheritance, and injected some polymorphic behavior using abstract methods and interface implementation. In the next article, I'll complete this C# primer by examining the remaining .NET types (enumerations, structures and delegates). See ya next issue, and happy hacking.


Andrew Troelsen is a seasoned .NET developer who has authored numerous books on the topic, including the award winning C# and the .NET Platform. He is employed as a full-time .NET trainer and consultant for Intertech Training (www.intertechtraining.com), but thinks he is still on the beaches of Mexico sipping funky drinks served in coconut shells. You can contact Andrew at atroelsen@mac.com.

 
AAPL
$97.67
Apple Inc.
+1.41
MSFT
$43.63
Microsoft Corpora
+0.89
GOOG
$511.17
Google Inc.
-13.34

MacTech Search:
Community Search:

Software Updates via MacUpdate

MenuMeters 1.8 - CPU, memory, disk, and...
MenuMeters is a set of CPU, memory, disk, and network monitoring tools for Mac OS X. Although there are numerous other programs which do the same thing, none had quite the feature set I was looking... Read more
Coda 2.5 - One-window Web development su...
Coda is a powerful Web editor that puts everything in one place. An editor. Terminal. CSS. Files. With Coda 2, we went beyond expectations. With loads of new, much-requested features, a few... Read more
Arq 4.6.1 - Online backup to Google Driv...
Arq is super-easy online backup for the Mac. Back up to your own Google Drive storage (15GB free storage), your own Amazon Glacier ($.01/GB per month storage) or S3, or any SFTP server. Arq backs up... Read more
Airfoil 4.8.10 - Send audio from any app...
Airfoil allows you to send any audio to AirPort Express units, Apple TVs, and even other Macs and PCs, all in sync! It's your audio - everywhere. With Airfoil you can take audio from any... Read more
Apple iMovie 10.0.6 - Edit personal vide...
With an all-new design, Apple iMovie lets you enjoy your videos like never before. Browse your clips more easily, instantly share your favorite moments, and create beautiful HD movies and Hollywood-... Read more
OnyX 2.8.8 - Maintenance and optimizatio...
OnyX is a multifunctional utility for OS X. It allows you to verify the startup disk and the structure of its System files, to run miscellaneous tasks of system maintenance, to configure the hidden... Read more
Parallels Desktop 10.1 - Run Windows app...
Parallels Desktop is simply the world's bestselling, top-rated, and most trusted solution for running Windows applications on your Mac. With Parallels Desktop for Mac, you can seamlessly run both... Read more
Apple Keynote 6.5 - Apple's present...
Apple Keynote makes it simple to create and deliver beautiful presentations. Powerful tools and dazzling effects bring your ideas to life. You can work seamlessly between Mac and iOS devices. And... Read more
OmniPlan 2.3.7 - Robust project manageme...
With OmniPlan, you can create logical, manageable project plans with Gantt charts, schedules, summaries, milestones, and critical paths. Break down the tasks needed to make your project a success,... Read more
Flavours 1.1.16 - Create and apply theme...
Flavours is a Mac application that allow users to create, apply and share beautifully designed themes. Classy Give your Mac a gorgeous new look by applying delicious themes! Easy Unleash your... Read more

Latest Forum Discussions

See All

My Very Hungry Caterpillar (Education)
My Very Hungry Caterpillar 1.0.0 Device: iOS Universal Category: Education Price: $3.99, Version: 1.0.0 (iTunes) Description: Care for your very own Very Hungry Caterpillar! My Very Hungry Caterpillar will captivate you as he crawls... | Read more »
Dungeon Dick (Games)
Dungeon Dick 1.1 Device: iOS Universal Category: Games Price: $.99, Version: 1.1 (iTunes) Description: Dungeon Dick is a fantasy adventure where you must discover the wicked plot to destroy the lands . 'Fling' at your foes and land... | Read more »
Here’s How the Apple Watch Could Transfo...
With the Apple Watch’s generic release date of, “early 2015” hovering on the horizon, it’s only a matter of time before gamers begin to ask “What’s in it for us?” The obvious choice would be to place entire games directly on the face of the watch,... | Read more »
Republique Episode 3: Ones & Zeroes...
Republique Episode 3: Ones & Zeroes is Available Now Posted by Rob Rich on October 17th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Loot Raiders Review
Loot Raiders Review By Campbell Bird on October 17th, 2014 Our Rating: :: PRESS BUTTON, GET LOOTUniversal App - Designed for iPhone and iPad This menu-based loot game is suitable to compel those with pretty extreme loot lust.   | Read more »
Angry Birds are Crashing Puzzle & Dr...
Angry Birds are Crashing Puzzle & Dragons Next Week Posted by Rob Rich on October 17th, 2014 [ permalink ] Next week, Puzzle & Dragons is getting a little angry. Because, you know, Angry Birds. It’s a… a pun. I thought… never mind. | Read more »
Incandescence Review
Incandescence Review By Andrew Fisher on October 17th, 2014 Our Rating: :: ALL TAPPED OUTUniversal App - Designed for iPhone and iPad Incandescence promises intense tapping action, but isn’t particularly fun.   | Read more »
Lion Pig (Games)
Lion Pig 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: "Leaving aside the biology of how a pig and a lion might meet, fall in love, and create this curious cross-breed, Lion Pig is a... | Read more »
Zero Lives (Games)
Zero Lives 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Zero Lives is a puzzle game. Simple and elegant at its core but deep and captivating the more you play. Each puzzle will challenge... | Read more »
#SUPERHYPER (Games)
#SUPERHYPER 001 Device: iOS Universal Category: Games Price: $.99, Version: 001 (iTunes) Description: "This is a game that fans of challenging minimalist arcade games, not to mention pixel art, should keep an eye on" - Touch Arcade "... | Read more »

Price Scanner via MacPrices.net

Apple Pay Available to Millions of Visa Cardh...
Visa Inc. brings secure, convenient payments to iPad Air 2 and iPad mini 3as well as iPhone 6 and 6 Plus. Starting October 20th, eligible Visa cardholders in the U.S. will be able to use Apple Pay,... Read more
Textkraft Pocket – the missing TextEdit for i...
infovole GmbH has announced the release and immediate availability of Textkraft Pocket 1.0, a professional text editor and note taking app for Apple’s iPhone. In March 2014 rumors were all about... Read more
C Spire to offer iPad Air 2 and iPad mini 3,...
C Spire on Friday announced that it will offer iPad Air 2 and iPad mini 3, both with Wi-Fi + Cellular, on its 4G+ LTE network in the coming weeks. C Spire will offer the new iPads with a range of... Read more
Belkin Announces Full Line of Keyboards and C...
Belkin International has unveiled a new lineup of keyboard cases and accessories for Apple’s newest iPads, featuring three QODE keyboards and a collection of thin, lightweight folios for both the... Read more
Verizon offers new iPad Air 2 preorders for $...
Verizon Wireless is accepting preorders for the new iPad Air 2, cellular models, for $100 off MSRP with a 2-year service agreement: - 16GB iPad Air 2 WiFi + Cellular: $529.99 - 64GB iPad Air 2 WiFi... Read more
Price drops on refurbished Mac minis, now ava...
The Apple Store has dropped prices on Apple Certified Refurbished previous-generation Mac minis, with models now available starting at $419. Apple’s one-year warranty is included with each mini, and... Read more
Apple refurbished 2014 MacBook Airs available...
The Apple Store has Apple Certified Refurbished 2014 MacBook Airs available for up to $180 off the cost of new models. An Apple one-year warranty is included with each MacBook, and shipping is free.... Read more
Refurbished 2013 MacBook Pros available for u...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available starting at $929. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros (4GB RAM/... Read more
WaterField Designs Unveils Outback iPad Slip...
Fresh on the heels of Apple’s announcement Thursday, WaterField Designs unveils its new Outback Slip Case for the iPad Air 2 and iPad mini 3 — a custom-fitted case for the just-announced Apple iPads... Read more
Apple Introduces iPad Air 2 & iPad mini 3...
Apple on Thursday introduced iPad Air 2, slimmed down again to just 6.1 mm, and weighing less than a pound. iPad Air 2 also features an improved Retina display claimed to deliver enhanced contrast... Read more

Jobs Board

Position Opening at *Apple* - Apple (United...
**Job Summary** At the Apple Store, you connect business professionals and entrepreneurs with the tools they need in order to put Apple solutions to work in their Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** The Apple Store is a retail environment like no other - uniquely focused on delivering amazing customer experiences. As an Expert, you introduce people Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** As businesses discover the power of Apple computers and mobile devices, it's your job - as a Solutions Engineer - to show them how to introduce these Read more
Position Opening at *Apple* - Apple (United...
…Summary** As a Specialist, you help create the energy and excitement around Apple products, providing the right solutions and getting products into customers' hands. You Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.