Wednesday 21 December 2011

Lesson 13: Interfaces

This lesson teaches C# Interfaces. Our objectives are as follows:
  • Understand the Purpose of Interfaces.
  • Define an Interface.
  • Use an Interface.
  • Implement Interface Inheritance.
An interface looks like a class, but has no implementation. The only thing it contains are declarations of events, indexers, methods and/or properties. The reason interfaces only provide declarations is because they are inherited by classes and structs, which must provide an implementation for each interface member declared.
So, what are interfaces good for if they don't implement functionality? They're great for putting together plug-n-play like architectures where components can be interchanged at will. Since all interchangeable components implement the same interface, they can be used without any extra programming. The interface forces each component to expose specific public members that will be used in a certain way.
Because interfaces must be implemented by derived classes and structs, they define a contract. For instance, if class foo implements the IDisposable interface, it is making a statement that it guarantees it has the Dispose() method, which is the only member of the IDisposable interface. Any code that wishes to use class foo may check to see if class foo implements IDisposable. When the answer is true, then the code knows that it can call foo.Dispose(). Listing 13-1 shows how to define an interface:
Listing 13-1. Defining an Interface: MyInterface.cs
interface IMyInterface
{
    void MethodToImplement();
}

Listing 13-1 defines an interface named IMyInterface. A common naming convention is to prefix all interface names with a capital "I". This interface has a single method named MethodToImplement(). This could have been any type of method declaration with different parameters and return types. I just chose to declare this method with no parameters and a void return type to make the example easy. Notice that this method does not have an implementation (instructions between curly braces - {}), but instead ends with a semi-colon, ";". This is because the interface only specifies the signature of methods that an inheriting class or struct must implement. Listing 13-2 shows how this interface could be used.

Lesson 12: Structs

This lesson will teach you about the C# struct. Our objectives are as follows:
  • Understand the Purpose of structs.
  • Implement a struct.
  • Use a struct.

What is a struct?

A struct is a value type. To help understand the struct, it's helpful to make a comparison with classes, as described in Lesson 7: Introduction to Classes and subsequent chapters. While a struct is a value type, a class is a reference type. Value types hold their value in memory where they are declared, but reference types hold a reference to an object in memory. If you copy a struct, C# creates a new copy of the object and assigns the copy of the object to a separate struct instance. However, if you copy a class, C# creates a new copy of the reference to the object and assigns the copy of the reference to the separate class instance. Structs can't have destructors, but classes can have destructors. Another difference between a struct and class is that a struct can't have implementation inheritance, but a class can, as described in Lesson 8: Class Inheritance. Although a struct can't have implementation inheritance, it can have interface inheritance, as described in Lesson 13: Interfaces, which is the next lesson following this one. Lesson 22: Topics on C# Type, digs deeper into the differences between value and reference types, providing code that demonstrates the concepts that are introduced here.
The .NET Framework includes many types that are structs, including many of the built-in types. For example, a System.Int32 is a C# int, a System.Single is a C# float, and a System.Bool is a C# bool. The C# built-in types are aliases for .NET Framework types, giving you language-specific syntax. If you look at the documentation for any of these .NET Framework types, you'll see them declared as struct types. That means you'll need to recognize what a struct type is when you see it, which the next section helps with by showing you how to create your own custom struct type.

Creating a Custom struct Type

While the behavior of class and struct types are very different, their syntax is similar. You declare the type and its members with the primary visual difference being that a struct uses the keyword struct and a class uses the keyword class. The example in Listing 12-1 demonstrates how to define a custom struct. In this case, the struct is a Rectangle with Width and Height properties, similar to what you might use to represent a rectangular shape on a screen.
Listing 12-1. Defining a struct
/// <summary>
/// Custom struct type, representing
    a rectangular shape
/// </summary>
struct Rectangle
{
    /// <summary>
    /// Backing Store for Width
    /// </summary>
    private int m_width;

    /// <summary>
    /// Width of rectangle
    /// </summary>
    public int Width 
    {
        get
        {
            return m_width;
        }
        set
        {
            m_width = value;
        }
    }

    /// <summary>
    /// Backing store for Height
    /// </summary>
    private int m_height;

    /// <summary>
    /// Height of rectangle
    /// </summary>
    public int Height
    {
        get
        {
            return m_height;
        }
        set
        {
            m_height = value;
        }
    }
}
As you can see, the Rectangle struct in Listing 12-1 looks very much like a class with a couple properties, except that it uses the keyword struct, instead of the keyword class, to declare that Rectangle is a struct.

Lesson 11: Indexers

This lesson teaches C# Indexers. Our objectives are as follows:
  • Understand What Indexers Are For.
  • Implement an Indexer.
  • Overload Indexers.
  • Understand How to Implement Multi-Parameter Indexers.
Indexers allow your class to be used just like an array. On the inside of a class, you manage a collection of values any way you want. These objects could be a finite set of class members, another array, or some complex data structure. Regardless of the internal implementation of the class, its data can be obtained consistently through the use of indexers. Here's an example.
Listing 11-1. An Example of An Indexer: IntIndexer.cs
using System;

/// <summary>
///
     A simple indexer example.
/// </summary>
class IntIndexer
{
    private string[] myData;

    public IntIndexer(int size)
    {
        myData =
new string[size];

        for (int i=0; i < size; i++)
        {
            myData[i] = "empty";
        }
    }

    public
string this[int pos]
    {
        get
       {
            return myData[pos];
        }
        set
       {
            myData[pos] =
value;
        }
    }

    static
void Main(string[] args)
    {
        int size = 10;

        IntIndexer myInd =
new IntIndexer(size);

        myInd[9] = "Some Value";
        myInd[3] = "Another Value";
        myInd[5] = "Any Value";

        Console.WriteLine("\nIndexer Output\n");

        for
(int i=0; i < size; i++)
        {
            Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
        }
    }
}


Lesson 10: Properties

This lesson teaches C# Properties. Our objectives are as follows:
  • Understand What Properties Are For.
  • Implement a Property.
  • Create a Read-Only Property.
  • Create a Write-Only Property.
  • Create an auto-implemented property.

Overview of Properties

Properties provide the opportunity to protect a field in a class by reading and writing to it through the property. In other languages, this is often accomplished by programs implementing specialized getter and setter methods. C# properties enable this type of protection while also letting you access the property just like it was a field.
Another benefit of properties over fields is that you can change their internal implementation over time. With a public field, the underlying data type must always be the same because calling code depends on the field being the same. However, with a property, you  can change the implementation. For example, if a customer has an ID that is originally stored as an int, you might have a requirements change that made you perform a validation to ensure that calling code could never set the ID to a negative value. If it was a field, you would never be able to do this, but a property allows you to make such a change without breaking code. Now, lets see how to use properties.

Traditional Encapsulation Without Properties

Languages that don't have properties will use methods (functions or procedures) for encapsulation. The idea is to manage the values inside of the object, state, avoiding corruption and misuse by calling code. Listing 10-1 demonstrates how this traditional method works, encapsulating Customer information via accessor methods.

Lesson 9: Polymorphism

This lesson teaches about Polymorphism in C#. Our objectives are as follows:
  • Learn What Polymorphism Is.
  • Implement a Virtual Method.
  • Override a Virtual Method.
  • Use Polymorphism in a Program.
Another primary concept of object-oriented programming is Polymorphism. It allows you to invoke derived class methods through a base class reference during run-time. This is handy when you need to assign a group of objects to an array and then invoke each of their methods. They won't necessarily have to be the same object type. However, if they're related by inheritance, you can add them to the array as the inherited type. Then if they all share the same method name, that method of each object can be invoked. This lesson will show you how to accomplish this.
Listing 9-1. A Base Class With a Virtual Method: DrawingObject.cs