Saturday, December 22, 2007

Comparing and Sorting
The .NET Framework includes a standard set of interfaces that are used for comparing and sorting objects. Although implementing these interfaces is optional, any class that does implement them can interact with other .NET Framework classes to achieve greater functionality. In this section, you’ll see how these interfaces make it possible to compare and sort instances of your types, in the same way the built-in types are used.

Creating Comparable Types with the IComparable Interface
The IComparable interface can be implemented by types to provide a standard way of comparing multiple objects. By implementing IComparable, types can maintain reference equality semantics while providing a standard method for value comparison.

The IComparable interface is declared as follows:

interface IComparable
{
int CompareTo(object obj);
}
The CompareTo method returns one of the following three possible values:

Less than 0 if the current object compares as less than obj

0 if the current object compares as equal to obj

Greater than 0 if the current object compares as greater than obj

The following code shows an example of a simple value type that implements IComparable. The ZipCode structure models a U.S. postal ZIP Code, including the optional “plus 4” digits that help further define the destination. The IComparable.CompareTo method is used to enable comparison of multiple ZipCode objects.

public struct ZipCode: IComparable
{
public ZipCode(string zip, string plusFour)
{
_zip = zip;
_plusFour = plusFour;
}

public ZipCode(string zip)
{
_zip = zip;
_plusFour = null;
}

public int CompareTo(object obj)
{
if(obj == null)
return 1;

if(obj.GetType() != this.GetType())
throw new ArgumentException("Invalid comparison");

ZipCode other = (ZipCode)obj;
int result = _zip.CompareTo(other._zip);
if(result == 0)
{
if(other._plusFour == null)
result = _plusFour == null? 1: 0;
else
result = _plusFour.CompareTo(other._plusFour);
}
return result;
}

public override string ToString()
{
string result;
if(_plusFour != null && _plusFour.Length != 0)
result = string.Format("{0}-{1}", _zip, _plusFour);
else
result = _zip;
return result;
}

string _zip;
string _plusFour;
}
The ZipCode class has two fields that are used to store the components that make up a U.S. ZIP Code. The ZipCode.ToString method is overridden to provide string formatting in the customary format of, for example, 92653 or 92653-8204 if a “plus 4” code is present. The method of most interest in the ZipCode class is CompareTo. Although the details of how two objects are compared will differ, all implementations of CompareTo will follow this general pattern:

public int CompareTo(object obj)
{
// If the other object is null, this object sorts as greater.
if(obj == null)
return 1;
// If there's a type mismatch, throw an exception.
if(obj.GetType() != this.GetType())
throw new ArgumentException("Invalid comparison");
// Return a result based on a comparison of the two objects.



}
An implementation of the CompareTo method should first test to see whether null was passed as a parameter. If so, the comparison should be short-circuited and a result greater than 0 should be returned to indicate that the current object compares as greater than null. It’s also important to test that the objects being compared have the same type or are of a comparable type. Other­wise, you can run into a scenario such as this one:

Orange anOrange;
Apple anApple;
int result = anOrange.CompareTo(anApple);
After adding support for IComparable to a class or a structure, you can make use of the type’s support for comparison in two ways. The first way is to directly call the CompareTo method to determine the relative sort order for two objects, as shown here:

ZipCode lagunaHills = new ZipCode("92653", "8204");
ZipCode redmond = new ZipCode("98052");
ZipCode phoenix = new ZipCode("85044");

int comparison = lagunaHills.CompareTo(redmond);
The second way to take advantage of IComparable is to leverage other types and methods in the .NET Framework that are aware of the IComparable interface. These types offer increased functionality when they’re used with classes and structures that implement IComparable. For example, the Array.Sort static method can be used to sort an array of types that implement IComparable, as shown here:

ZipCode [] codes = { lagunaHills, redmond, phoenix };
Array.Sort(codes);
foreach(ZipCode code in codes)
{
// Display sorted array of ZIP Codes.
Console.WriteLine(code);
}
The version of the Array.Sort method used here detects and uses the IComparable interface to determine the relative sort order of objects in the array. If you attempt to use this version of Sort with an array of objects that don’t implement IComparable, an InvalidOperationException will be thrown.

Building Comparison Classes with the IComparer Interface
The IComparable interface is useful for those cases in which there’s a clear ordering method for class instances. However, there are times when a number of possible sort methods are available for a collection of objects. The IComparer interface enables you to build classes that are specialized to compare instances of other classes.

The IComparer interface is declared as follows:

interface IComparer
{
int Compare(object x, object y);
}
The Compare method works much like the CompareTo method discussed in the previous section, returning one of the following values:

Less than 0 if the first object compares as less than the second object

0 if the first object compares as equal to the second object

Greater than 0 if the first object compares as greater than the second object

As with the IComparable.CompareTo method, if an object reference is null, it compares as less than any object.

Implementing IComparer in Pluggable Classes
The IComparer interface makes it possible for you to create multiple comparison classes, each of which performs a different type of comparison. The following class implements the IComparer interface and sorts ZipCode objects in ascending order:

public class AscendingComparer: IComparer
{
public int Compare(object x, object y)
{
int result = 0;
if(x == null && y == null)
result = 0;
else if(x == null)
result = -1;
else if(y == null)
result = 1;
else
{
if(x.GetType() != y.GetType())
throw new ArgumentException("Invalid comparison");
IComparable comp = x as IComparable;
if(comp == null)
throw new ArgumentException("Invalid comparison");
result = comp.CompareTo(y);
}
return result;
}
}
This code shows a common pattern for implementing IComparer.Compare. In much the same way as in the earlier IComparable example, any reference to null is sorted as less than object references. If two valid object references are compared, the types of the objects are tested to ensure that they’re comparable. In this case, the AscendingComparer class tests to verify that both objects have the same type.

The following code implements the DescendingComparer class, which works exactly like AscendingComparer except that it sorts its objects in reverse order:

public class DescendingComparer: IComparer
{
public int Compare(object x, object y)
{
int result = 0;
if(x == null && y == null)
result = 0;
else if(y == null)
result = -1;
else if(x == null)
result = 1;
else
{
if(x.GetType() != y.GetType())
throw new ArgumentException("Invalid comparison");
IComparable comp = y as IComparable;
if(comp == null)
throw new ArgumentException("Invalid comparison");
result = comp.CompareTo(x);
}
return result;
}
}
When sorting is required, you can simply plug in an instance of the preferred comparison class, allowing multiple sort options to be used for a single type. For example, the following code uses both of the previous comparison classes to sort ZipCode objects:

Array.Sort(codes, new AscendingComparer());
foreach(ZipCode code in codes)
{
Console.WriteLine(code);
}
Array.Sort(codes, new DescendingComparer());
foreach(ZipCode code in codes)
{
Console.WriteLine(code);
}
In the preceding examples, the AscendingComparer and DescendingComparer classes are exposed as public classes. Another alternative is to expose the classes that perform the comparison through properties, as shown here:

Array.Sort(codes, codes.AscendingComparer);



Array.Sort(codes, codes.DescendingComparer);



The advantage of this approach is that the comparison classes are more completely encapsulated, thus hiding more implementation details from the user.

Using the Built-In Comparison Classes
The .NET Framework includes two classes that implement the IComparer interface and can be leveraged in your own classes to simplify comparisons. The Comparer and CaseInsensitiveComparer classes provide basic implementations of IComparer that are suitable for many comparison classes. Both of these classes respect the culture preferences of the user, providing proper comparisons based on the locale and language settings associated with the current thread.

You never directly create an instance of the Comparer class using the new operator. Instead, you call the Default method, which returns a properly initialized Comparer object, as shown here:

Comparer theComparer = Comparer.Default;
After you have a Comparer object, you can delegate comparison calls to its Compare method. The following code illustrates a simplified version of AscendingComparer implemented using the Comparer class:

public int Compare(object x, object y)
{
return Comparer.Default.Compare(x, y);
}
In this code, ZipCode objects are passed to the Comparer class, which is able to properly compare the objects through their IComparable interface. This is the only way that Comparer can perform comparisons on arbitrary objects. If your classes don’t implement IComparable, you can’t pass instances of the classes to Comparer.Compare.

The CaseInsensitiveComparer class works much like the Comparer class, comparing any two objects through the IComparable interface, except that it performs a case-insensitive comparison on strings that it encounters. Like the Comparer class, the static Default method is used to obtain a reference to a properly initialized CaseInsensitiveComparer object, as shown here:

CaseInsensitiveComparer aComparer = CaseInsensitiveComparer.Default;
Unlike the Comparer class, you can use the new operator to create CaseInsensitiveComparer objects. The default constructor has little advantage over the Default method, other than enabling you to cache a specific Case­InsensitiveComparer object. An overloaded version of the constructor allows you to specify the culture to be used for the comparison. (The culture of the current thread is used by default.) The following code performs a string comparison using the Swedish culture definition:

public class SwedishNameComparer: IComparer
{
public int Compare(object x, object y)
{
CultureInfo ci = new CultureInfo("sv");
CaseInsensitiveComparer aComparer = null;
aComparer = new CaseInsensitiveComparer(ci);
return aComparer.Compare(x, y);
}
}





public Main()
{
string [] places = { "Kista", "Älvsjö", "Stockholm" };
Array.Sort(places, new SwedishNameComparer());
foreach(string place in places)
{
Console.WriteLine(place);
}
}
The preceding code sorts the strings according to the ordering used in Swedish, where Ä is placed after Z, as shown here:

Kista
Stockholm
Älvsjö
If the en-US (English as spoken in the United States) culture is used to sort the strings, the strings are sorted as follows:

Älvsjö
Kista
Stockholm
Which comparison is most appropriate? The answer depends on the expectations of the user, which are expressed in the culture settings associated with the current thread. Because the comparison classes included with the .NET Framework take the culture settings into account, they handle these sorting issues correctly.

Enumerators

Using Enumerators
Although the version of the AssociativeArray class presented in the previous section is useful, it has a limitation that restricts its use in a C# application. Because it doesn’t support the standard enumeration pattern used by classes in the .NET Framework, iterating over all elements in the array is difficult and requires client code to know the key for each element stored in the collection.

There are multiple ways that iteration over an associative array collection could be supported. One approach would be to expose an indexer that supports numerical indexing, allowing a loop similar to the following to be written:

for(int n = 0; n < foodFavorites.Length; ++n)
{
string favorite = foodFavorites[n];



}
The problem with this approach is that it can’t be generalized to all types of collections. For example, consider a collection class that stores items in a tree-based data structure. Although it would be possible to expose an indexer that provides indexing based on integer keys, it wouldn’t result in a natural access method for the container.

The .NET Framework offers a different approach for iterating over all items in a collection—the enumerator. Enumerators are classes used to provide a standard iteration method over all items stored in a collection. By specifying the standard interfaces used to implement enumerators, the .NET Framework formalizes a design pattern that’s used for all collection types. In this section, we’ll examine the standard interfaces used to build enumerators, and we’ll add enumerator support to the AssociativeArray class.

Understanding Enumeration Interfaces
Enumerators are classes that implement the IEnumerator interface, which is part of the System.Collections namespace. The IEnumerator interface, shown in the following code, is used to define a cursor-style iteration over a collection:

interface IEnumerator
{
object Current
{
get;
}
void Reset();
bool MoveNext();
}
The IEnumerator interface exposes two methods and one property:

Reset Returns the enumerator to its initial state

MoveNext Moves to the next item in the collection, returning true if the operation was successful or false if the enumerator has moved past the last item

Current Returns the object to which the enumerator currently refers

The IEnumerator interface isn’t implemented directly by collection classes; instead, it’s implemented by separate enumerator classes that provide enumeration functionality. Decoupling enumeration classes from the collection class makes it easy to support multiple simultaneous enumeration objects for one collection. If IEnumerator was to be implemented by a collection class, it would be difficult for a collection class to support more than one client using enumeration at any given time.



Multiple enumeration objects acting on a collection class concurrently.
Classes that support enumeration and want to expose enumerators to their clients implement the IEnumerable interface. IEnumerable includes a single method, GetEnumerator, which returns an enumerator object for the current object. The declaration for IEnumerable is shown here:

interface IEnumerable
{
IEnumerator GetEnumerator();
}
When enumerators are newly minted, the enumerator’s Current property can’t be used because it’s positioned just prior to the first item. To advance the enumerator to the first item in the collection, you must call MoveNext, which will return true if the enumerator is positioned at a valid collection item. This behavior allows you to write a very compact loop when iterating over a collection, as shown here:

IEnumerator enumerator = enumerable.GetEnumerator();
while(enumerator.MoveNext())
{
MyObject obj = (MyObject)enumerator.Current;



}
Enumerators are always tightly bound to a specific collection object. If the collection is updated, any enumerators associated with the collection are invalidated and can’t be used. If you attempt to use an enumerator after it’s been invalidated or when it’s positioned before the first element or after the last element, an InvalidOperationException exception will be thrown.

Implementing Enumeration Interfaces
The first step in implementing enumeration interfaces is to create an internal or embedded class that implements IEnumerator. Although you’ll create a concrete class derived from IEnumerator to implement the enumerator, you probably won’t expose this class as public. To prevent clients from depending on your specific enumerator declaration, it’s a much better idea to keep your enumerator class protected or private and expose functionality only through the IEnumerator interface.

Creating an Enumerator Class
In addition to implementing the IEnumerator interface, your enumerator class must be able to access individual items in the underlying collection. For the enumerator example presented in this section, the AssociativeArray class has been modified to make the _items field internal, granting access to any classes in the assembly, as shown here:

internal object[] _items;
Another approach is to implement an enumerator as a class that’s embedded in the collection class, as follows:

public class AssociativeArray: IEnumerable
{



public class AssociativeArrayEnumerator : IEnumerator
{



}
}
When an enumerator is implemented as a class embedded within the collection, it can access all members of the collection class, which can provide for better encapsulation. However, embedding the enumerator also increases the size and complexity of the collection class. For the purposes of this example, the enumerator class is broken out separately.

Regardless of the implementation of the enumerator, you’ll need to pass a reference to the collection to the enumerator when the enumerator is constructed and initialized, as shown here:

public IEnumerator GetEnumerator()
{
return new AssociativeArrayEnumerator(this);
}
Remember that you must provide a mechanism that enables the collection to invalidate any enumerators that are associated with the collection. This is the only way that users of the enumerator can determine that the collection has been updated. A good way to invalidate the enumerator is to provide an event that’s raised when the collection is updated. By subscribing to the event during construction, enumerators can receive an event notification and mark themselves invalid when their associated collection is changed.

An example of an enumerator that provides iteration access to the AssociativeArray class is shown here:

// An enumerator for the AssociativeArray class
public class AssociativeArrayEnumerator : IEnumerator
{
public AssociativeArrayEnumerator(AssociativeArray ar)
{
_ar = ar;
_currIndex = -1;
_invalidated = false;
// Subscribe to collection change events.
AssociativeArray.ChangeEventHandler h;
h = new AssociativeArray.ChangeEventHandler(InvalidatedHandler);
ar.AddOnChanged(h);
}
// Property that retrieves the element in the array that this
// enumerator instance is pointing to. If the enumerator has
// been invalidated or isn't pointing to a valid item, throw
// an InvalidOperationException exception.
public object Current
{
get
{
AssociativeArray.KeyItemPair pair;
if(_invalidated ││
_currIndex == -1 ││
_currIndex == _ar.Length)
throw new InvalidOperationException();
pair = (AssociativeArray.KeyItemPair)_ar._items[_currIndex];
return pair.item;
}
}
// Move to the next item in the collection, returning true if the
// enumerator refers to a valid item and returning false otherwise.
public bool MoveNext()
{
if(_invalidated ││ _currIndex == _ar._items.Length)
throw new InvalidOperationException();
_currIndex++;
if(_currIndex == _ar.Length)
return false;
else
return true;
}
// Reset the enumerator to its initial position.
public void Reset()
{
if(_invalidated)
throw new InvalidOperationException();
_currIndex = -1;
}
// Event handler for changes to the underlying collection. When
// a change occurs, this enumerator is invalidated and must be
// re-created.
private void InvalidatedHandler(object sender, EventArgs e)
{
_invalidated = true;
}
// Flag that marks the collection as invalid after a change to
// the associative array
protected bool _invalidated;
// The index of the item this enumerator applies to
protected int _currIndex;
// A reference to this enumerator's associative array
protected AssociativeArray _ar;
}
Providing Access to the Enumerator
You should create new enumerator objects in response to a call to the collection class’s GetEnumerator method. Although you’ll return your enumerator object, the client code that retrieves your enumerator has access to your object only through IEnumerator because GetEnumerator is typed to return only an IEnumerator interface. The version of GetEnumerator for the AssociativeArray class is shown here:

public class AssociativeArray: IEnumerable
{



public IEnumerator GetEnumerator()
{
return new AssociativeArrayEnumerator(this);
}



}
In response to the call to GetEnumerator, the AssociativeArray class creates a new enumerator object, passing the this pointer so that the enumerator can initialize itself to refer to this AssociativeArray object.

Other changes made to the AssociativeArray class to provide enumerator support are shown here:

public class AssociativeArray: IEnumerable
{
// Event delegate
public delegate void ChangeEventHandler(object sender, EventArgs e);



public AssociativeArray(int initialSize)
{
_count = 0;
_items = new object[initialSize];
_eventArgs = new EventArgs();
}



public void AddOnChanged(ChangeEventHandler handler)
{
Changed += handler;
}
// Remove an event handler for the changed event.
public void RemoveOnChanged(ChangeEventHandler handler)
{
Changed -= handler;
}
// Raise a changed event to subscribed enumerators.
protected void OnChanged()
{
if(Changed != null)
Changed(this, _eventArgs);
}



// Event handler for distributing change events to enumerators
public event ChangeEventHandler Changed;
// A member that holds change event arguments
protected EventArgs _eventArgs;
}
In addition to implementing IEnumerable, several changes have been made to the AssociativeArray class. First, an event delegate type has been declared to propagate events to enumerators. Next, the AddOnChanged and RemoveOnChanged methods have been added to assist in subscribing and unsubscribing to the Changed event. Each enumerator subscribes to this event so that the enumerators can be invalidated after changes to the AssociativeArray object. Instead of creating new EventArgs objects when each Changed event is raised, a single EventArgs object is created and passed for all events raised during the object’s lifetime.

Consuming Enumeration Interfaces
There are two ways to use the .NET Framework’s enumerator interfaces. The first method is to request the enumerator directly and explicitly iterate over the collection using the IEnumerator interface, like this:

public void Iterate(object obj)
{
IEnumerable enumerable = obj as IEnumerable;
if(enumerable != null)
{
IEnumerator enumerator = enumerable.GetEnumerator();
while(enumerator.MoveNext())
{
object theObject = enumerator.Current;
Console.WriteLine(theObject.ToString());
}
}
}
A more useful and common way to make use of the enumeration interfaces is to use a foreach loop, as shown in the following code.

static void Main(string[] args)
{
AssociativeArray foodFavorites = new AssociativeArray(4);
foodFavorites["Mickey"] = "Risotto with Wild Mushrooms";
foodFavorites["Ali"] = "Plain Cheeseburger";
foodFavorites["Mackenzie"] = "Macaroni and Cheese";
foodFavorites["Rene"] = "Escargots";

try
{
foreach(string food in foodFavorites)
{
Console.WriteLine(food);
}
}
catch(InvalidOperationException exc)
{
Console.WriteLine(exc.ToString());
}
}
Behind the scenes, the C# compiler will generate the code required to make use of IEnumerable and IEnumerator. When the preceding code is compiled and executed, the output looks like this:

Risotto with Wild Mushrooms
Plain Cheeseburger
Macaroni and Cheese
Escargots

Enumerations

Enumerations
An enumeration is a list of enumerated values that are associated with a specific type. Enumerations are declared using the enum keyword, as shown here:

enum Color
{
Red, Yellow, Green
}
An enumeration value is accessed using the dot operator.

Color background = Color.Red;
Unlike C++ enumerators, C# enumerators must be used with the enum type name. This reduces the likelihood of name clashes between enumerations and improves readability.

An enumeration assigns scalar values to each of the enumerators in the enumerated list. By default, the base type used to store enumerated values is int, which can be changed to any of the scalar types, as shown here:

enum Color : byte
{
Red, Yellow, Green
}
The values of enumerators begin at 0 unless an initial value is specified—in this case, 1:

enum Color : byte
{
Red = 1, Yellow, Green
}
Enumerators are assigned sequential values unless an initializer is specified for the enumerator. The value of an enumerator must be unique, but need not be sequential or ordered.

enum Color : byte
{
Red = 1, Yellow = 42, Green = 27
}
Although an enumerator is based on the int type (or another scalar value), you can’t assign an enumerator to or from an int value without being explicit about your intentions, as shown here:

Color background = (Color)27;
int oldColor = (int)background;

Structures

Structures
Like C and C++, C# includes support for creating structure types. A structure is an aggregate type that combines members of multiple types into a single new type. As with classes, members of a structure are private by default and must be explicitly made public to grant access to clients. A structure is declared using the struct keyword, as shown here:

struct Point
{
public int x;
public int y;
}
Structures and Inheritance
Structures can’t be inherited.

struct Point
{
public int x;
public int y;
}
// Not allowed; can't inherit from a struct.
class ThreeDPoint: Point
{
public int z;
}
This is in contrast to C++, in which there’s very little real difference between a class and a structure. In C#, structures can inherit from interfaces, but they’re not allowed to inherit from classes or other structures.

Allocating Structures
Unlike instances of classes, structures are never heap-allocated; they’re allocated on the stack. Staying out of the heap makes a structure instance much more efficient at runtime than a class instance in some cases. For example, creating large numbers of temporary structures that are used and discarded within a single method call is more efficient than creating objects from the heap. On the other hand, passing a structure as a parameter in a method call requires a copy of the structure to be created, which is less efficient than passing an object reference.

Creating an instance of a structure is just like creating a new class instance, as shown here:

Point pt = new Point();
Always use the dot operator to gain access to members of a structure.

pt.y = 5;

Member Functions
Structures can have member functions in addition to member fields. Structures can also have constructors, but the constructor must have at least one parameter, as shown here:

struct Rect
{
public Rect(Point topLeft, Point bottomRight)
{
top = topLeft.y;
left = topLeft.x;
bottom = bottomRight.y;
right = bottomRight.x;
}
// Assumes a normalized rectangle
public int Area()
{
return (bottom - top)*(right - left);
}
// Rectangle edges
int top, bottom, left, right;
}
Structures aren’t allowed to declare a destructor.

Managing Errors with Exceptions
All nontrivial software programs are subject to errors. These errors can come in many forms, such as coding errors, runtime errors, or errors in cooperating systems. Regardless of the form that an error takes or where it’s detected, each of these errors must be handled in some way. In C#, all errors are considered exceptional events that are managed by an exception handling mechanism.

Exception handling provides a robust way to handle errors, transferring control and rich error information when an error occurs. When an exception is raised, control is transferred to an appropriate exception handler, which is responsible for recovering from the error condition.

Code that uses exceptions for error handling tends to be clearer and more robust than code that uses other error handling methods. Consider the following code fragment that uses return values to handle errors:

bool RemoveFromAccount(string AccountId, decimal Amount)
{
bool Exists = VerifyAccountId(AccountId);
if(Exists)
{
bool CanWithdraw = CheckAvailability(AccountId, Amount);
if(CanWithdraw)
{
return Withdraw(AccountId, Amount);
}
}
return false;
}
Code that depends on return values for error detection has the following problems:

In cases in which a bool value is returned, detailed information about the error must be provided through additional error parameters or by calling additional error handling functions. This is the approach taken by much of the Win32 API.

Returning an error or a success code requires each programmer to properly handle the error code. The error code can be easily ignored or interpreted incorrectly, and an error condition might be missed or misinterpreted as a result.

Error codes are difficult to extend or update. Introducing a new error code might require updates throughout your source code.

In C#, error information is passed with exceptions. Rather than return a simple error code or a bool value, a method that fails is expected to raise an exception. The exception is a rich object that contains information about the failure condition.

Handling Exceptions
To handle an exception, you must protect a block of code using a try block and provide at least one catch block to handle the exception, as shown here:

try
{
Dog d;
// Attempt to call through a null reference.
d.ChaseCars();



}
catch
{
// Handle any exception.



}
When an exception is raised, or thrown, within a try block, an exception object of the proper type is created and a search begins for an appropriate catch clause. In the preceding example, the catch clause doesn’t specify an exception type and will catch any type of exception. Program execution is transferred immediately to the catch clause, which can perform one of these actions:

Handle the exception and continue execution after the catch clause

Rethrow the current exception

To catch only a specific exception, the catch clause supplies a parameter that serves as a filter, specifying the exception or exceptions that it’s capable of handling, as shown here:

try
{
Dog d;
// Attempt to call through a null reference.
d.ChaseCars();



}
catch(NullReferenceException ex)
{
// Handle only null reference exceptions.



}
If the catch clause can recover from the error that caused the exception, execution can continue after the catch clause. If the catch clause can’t recover, it should rethrow the exception so that another exception handler can try to recover from the error.

To rethrow an exception, the throw keyword is used with the exception object passed to the catch clause, as in the following example:

try
{
Dog d;
// Attempt to call through a null reference.
d.ChaseCars();
}
catch(NullReferenceException ex)
{
// (ex);
Log error information.
LogError (ex);
// Rethrow the exception.
throw(ex);
}
To rethrow the current exception, the throw keyword can be used without specifying an exception object, as shown here:

catch(NullReferenceException ex)
{



// Rethrow the current exception.
throw;
}
In a general catch block, throw must be used by itself, as there is no exception object to be rethrown:

catch
{



// Rethrow the current exception.
throw;
}
If an exception is rethrown, a search is performed for the next catch clause capable of handling the exception. The call stack is examined to determine the sequence of methods that have participated in calling the current method. Each method in the call stack can potentially handle the exception, with the exception being offered first to the immediate calling method if an acceptable catch clause exists. This sequence continues until the exception is handled, or until all methods in the call stack have had an opportunity to handle the exception. If no handler for the exception is found, the thread is terminated due to the unhandled exception.

Using Exception Information
A reasonable description of the exception can be retrieved from any of the .NET Framework exceptions by calling the exception object’s ToString method, as shown here:

catch(InvalidCastException badCast)
{
Console.WriteLine(badCast.ToString());
}
Other information is available from exception objects, as described here:

StackTrace Returns a string representation of a stack trace that was captured when the exception was thrown

InnerException Returns an additional exception that might have been saved during exception processing

Message Returns a localized string that describes the exception

HelpLink Returns a URL or Universal Resource Name (URN) to more information about the exception

If you create your own exception types that are exposed to others, you should provide at least this information. By providing the same information included with .NET Framework exceptions, your exceptions will be much more usable.

Providing Multiple Exception Handlers
If code is written in such a way that more than one type of exception might be thrown, multiple catch clauses can be appended, with each clause evaluated sequentially until a match for the exception object is found. At most, one of the catch clauses can be a general clause with no exception type specified, as shown here:

try
{
Dog d = (Dog)anAnimal;
}
catch(NullReferenceException badRef)
{
// Handle null references.



}
catch(InvalidCastException badCast)
{
// Handle a bad cast.



}
catch
{
// Handle any remaining type of exception.



}
The catch clauses are evaluated sequentially, which means that the more general catch clauses must be placed after the more specific catch clauses. The Visual C# compiler enforces this behavior and won’t compile poorly formed catch clauses such as this:

try
{
Dog d = (Dog)anAnimal;
}
catch(Exception ex)
{
// Handle any exception.
}
catch(InvalidCastException badCast)
{
// Handle a bad cast.
}
In this example, the first catch clause will handle all exceptions, with no exceptions passed to the second clause, so an invalid cast exception won’t receive the special handling you expected. Because this is obviously an error, the compiler rejects this type of construction.

It’s also possible to nest exception handlers, with try-catch blocks located within an enclosing try-catch block, as shown here:

try
{
Animal anAnimal = GetNextAnimal();
anAnimal.Eat();
try
{
Dog d = (Dog)anAnimal;
d.ChaseCars();
}
catch(InvalidCastException badCast)
{
// Handle bad casts.



}
}
catch
{
// General exception handling



}
When an exception is thrown, it’s first offered to the most immediate set of catch clauses. If the exception isn’t handled or is rethrown, it’s offered to the enclosing try-catch block.

Guaranteeing Code Execution
When you’re creating a method, sometimes there are tasks that must be executed before the method returns to the caller. Often this code frees resources or performs other actions that must occur even in the presence of exceptions or other errors. C# allows you to place this code into a finally clause, which is guaranteed to be executed before the method returns, as shown here:

try
{
Horse silver = GetHorseFromBarn();
silver.Ride();
}
catch
{



}
finally
{
silver.Groom();
}
In this example, the finally clause is executed after the exception is thrown. A finally clause is also executed if a return, goto, continue, or break statement attempts to transfer control out of the try clause.

As you can see, you can have a finally clause and catch clauses attached to the same try clause. If a catch clause rethrows an exception, control is first passed to the finally clause before it’s transferred out of the method.

.NET Framework Exceptions
The .NET Framework includes a large number of exception classes. Although all exceptions are eventually derived from the Exception class in the System namespace, the design pattern used in .NET is to include exceptions in the namespaces that generate the exceptions. For example, exceptions that are thrown by IO classes are located in the System.IO namespace.

Exceptions in the .NET Framework are rarely directly inherited from the System.Exception class. Instead, they’re clustered into categories, with a common subclass that enables clients to group similar exceptions together. For example, all IO exceptions are subclasses of the System.IO.IOException class, which is derived from System.Exception. This hierarchical relationship enables clients to write exception handlers that handle IO-specific errors in a single catch block without the need to write separate handlers for each exception, as shown here:

catch(IOException ioError)
{
// Handle all IO exceptions here.



}
When developing your own exception classes, consider following this pattern and deriving your classes from one of the many subclasses rather than deriving directly from the System.Exception class. Doing so will make your exceptions more usable by client code and might enable clients to handle exceptions thrown by your classes without requiring any new code.

Casting

Casting
In C#, a cast is used to explicitly convert a value or a reference to a different type. A cast is performed with a cast operator, which is a type enclosed in parentheses, as shown here:

Type T2 newType = (T2)oldType;
Casting isn’t required when you’re assigning a subclass to a base class reference because subclasses can always be substituted for a base class. However, the reverse is not true.

// OK; assignment to base reference.
Animal a = aDog;

// Error; requires a cast.
Dog d = anAnimal;

// Conversion OK with a cast.
Dog d2 = (Dog)anAnimal;
Explicit casting is required in this case because, in general, a client that expects functionality found in a subclass can’t assume that the base class also contains the same functionality. If you’re sure that a reference to a base class is actually a reference to the derived class, a cast will perform the conversion for you. But what if the cast can’t be performed, perhaps because an unexpected subclass has been encountered? Performing a cast is inherently unsafe—any attempt to perform a conversion can fail if the conversion isn’t allowed. When a conversion fails, an InvalidCastException is raised, as shown in this somewhat contrived example, in which a Cat object is passed to a method that was expecting a Dog object:

class Animal
{
public void Eat()
{
Console.WriteLine("Eating");
}
}

class Cat: Animal
{
public void ChaseBirds()
{
Console.WriteLine("Chasing birds");
}
}

class Dog: Animal
{
public void ChaseCars()
{
Console.WriteLine("Chasing cars");
}
}

class TestAnimal
{
static void ChaseACar(Animal anAnimal)
{
Dog d = (Dog)anAnimal;
d.ChaseCars();
}

static void Main()
{
Cat c = new Cat();
ChaseACar(c);
}
}
To handle invalid cast exceptions, casts that aren’t absolutely safe should provide the necessary exception handling, as shown here:

static void ChaseACar(Animal anAnimal)
{
try
{
Dog d = (Dog)anAnimal;
d.ChaseCars();
}
catch(InvalidCastException badCast)
{
// Error-recovery code
}
}
The compiler can’t, in general, catch invalid casting errors during compilation—these errors can be detected reliably only at runtime. Sometimes raising an exception is too drastic, however; often it’s more appropriate to attempt a conversion and take alternative actions if the conversion fails. In C#, you can attempt a conversion without raising an exception by using the as keyword, as follows:

Dog d = anAnimal as Dog;
Like a cast, as will attempt to convert a source type to a different target type, but unlike a cast, the as keyword won’t raise an exception if the conversion fails. Instead, the reference will be set to null so that the failure is easily detected programmatically.

static void ChaseACar(Animal anAnimal)
{
Dog d = anAnimal as Dog;
if(d != null)
d.ChaseCars();
else
Console.WriteLine("Not a dog");
}

Converting Types

Converting Types
The C# programming language puts a high value on type safety. Every value in a C# program has a specific type, and each type has a unique contract to which the type adheres. When a value is assigned to a variable that has a different type, a type conversion is required.

Type conversion is used to migrate values from one type to another. When a new type is defined, such as the BattingAverage type in the previous section, type conversion is often used to integrate the new type into existing code. For example, later in this section we’ll add some type conversion operators to simplify converting a BattingAverage object to a string or float value. Understanding how C# type conversion works can make your types much easier to use.

Performing Implicit Conversions
Some type conversions are inherently safe and are allowed to occur automatically, without any conversion code required. When you’re converting between scalar types, some conversions are guaranteed to succeed. For example, scalar types such as short, int, and long differ only in the range of values they can store. A short value can always be stored in an int, and an int can always be stored in a long, without writing any conversion code, as shown here:

short s = 32767;
int n = s;
One characteristic of these implicit conversions is that they are inherently asymmetrical, meaning that you can implicitly store a short value in an int, but a conversion in the other direction can potentially result in the loss of data, and can’t be done implicitly by the compiler.

Performing Explicit Conversions
Conversions that result in a loss of data require you to write code that explicitly demands that a conversion take place. Examples of conversions that must be managed explicitly are a conversion that results in a loss of precision or a conversion to a scalar type with a smaller range.

Many times, a conversion that might result in a loss of data is actually harmless. For example, a conversion from a double to a float results in a loss of precision; in your application, however, the degradation in precision might be a harmless conversion. A value stored as a long can be safely converted to an int if you know that its value will always fall into the range permitted for an int.

The brute-force way to explicitly convert a value from one type to a type that might result in a loss of data is to use the cast operator. As discussed earlier in this chapter in the section “Using Other Operators,” to use the cast operator, you enclose the new type in parentheses and place it to the left of the value to be cast, as shown here:

int longVal = 32767;
short s = (short)longVal;
Another method that can be used to convert types is to use the System.Convert class, as discussed in the next section.

String conversion can be accomplished in multiple ways, one of which is to override the ToString method. The object base class implements a default version of ToString, and most types override that implementation and provide a new version of ToString that converts the object’s value to a string. For the BattingAverage type, the ToString method has been overridden first to calculate the batting average and then to format the text as a string in the traditional batting average format, with three digits to the left of the decimal point, as shown here:

// Convert the batting average to a string.
public override string ToString()
{
float average = Average();
string result = string.Format("{0:#.000}", average);
return result;
}
Overriding the Object.ToString method simplifies the use of the Batting­Average type when you’re formatting text. For example, when a BattingAverage object is passed to the Console.WriteLine method, the Console class will use the ToString method to retrieve the text that’s sent to the console. With the following code, a batting average of .333 is displayed to the user:

// 30 at bats, 10 hits
BattingAverage ba = new BattingAverage(30, 10);
Console.WriteLine(ba);
Using the Convert Class
The Convert class offers a convenient way to convert values to different types, even if the types are unrelated. The Convert class has an added feature: the current culture settings are respected, so symbols such as the decimal separator are formatted correctly.

All methods in the Convert class are static, so you never need to create a Convert object. The following code uses the Convert class to convert a string value to an int value:

string stringValue = "1542";
int intValue = Convert.ToInt32(stringValue);
Each of the ToXxxx methods is used to convert a value to one of the primitive .NET types, where Xxxx is a .NET type name such as Int16, Int32, or String. The class overloads these methods for ease of use (the ToInt32 method, for example, can convert several different types to an Int32), with some methods offering dozens of overloads.

Performing User-Defined Conversions
A user-defined conversion is a type-conversion method supplied by a class or structure that defines how an object of that type can be converted to another type. In C#, user-defined conversions serve a role similar to that of the C++ cast operator, but they allow more flexibility. A user-defined conversion can be defined as either implicit or explicit. Implicit conversions can occur automatically when a parameter is passed to a method or during an assignment. Explicit conversions take place only if the cast operator is used. If a conversion can result in a loss of data, you should define the conversion as explicit.

All conversions must abide by the following rules:

A user-defined conversion isn’t allowed to convert a type to the same type, or to a subclass or superclass of the type.

User-defined conversions must be to or from the type defining the conversion.

Conversion can’t be attempted to or from an interface or the object type.

These rules help provide predictable behavior for user-defined conversions as well as prevent interference with built-in conversions.

User-defined conversion operators accept a single type as a parameter. An explicit user-defined conversion for the BattingAverage type to float looks like this:

public static explicit operator float(BattingAverage avg)
{
return avg.Average();
}
To define an implicit conversion, simply use the implicit keyword instead of explicit as was done in this example. Here the choice of an implicit or explicit conversion is a judgment call, as the conversion doesn’t actually cause any data loss. However, because an implicit conversion would allow the Batting­Average type to be substituted for the float type for any method parameters or assignment, the preceding code requires the caller to use a cast operator for the conversion.