Guidelines for Casting Types
The following rules outline the usage guidelines for casts:
• Do not allow implicit casts that will result in a loss of precision. For example, there should not be an implicit cast from Double to Int32, but there might be one from Int32 to Int64.
• Do not throw exceptions from implicit casts because it is very difficult for the developer to understand what is happening.
• Provide casts that operate on an entire object. The value that is cast should represent the entire object, not a member of an object. For example, it is not appropriate for a Button to cast to a string by returning its caption.
• Do not generate a semantically different value. For example, it is appropriate to convert a DateTime or TimeSpan into an Int32. The Int32 still represents the time or duration. It does not, however, make sense to convert a file name string such as "c:\mybitmap.gif" into a Bitmap object.
• Do not cast values from different domains. Casts operate within a particular domain of values. For example, numbers and strings are different domains. It makes sense that an Int32 can cast to a Double. However, it does not make sense for an Int32 to cast to a String, because they are in different domains.
Common Design Patterns
Implementing Finalize and Dispose to Clean Up Unmanaged Resources
Class instances often encapsulate control over resources that are not managed by the runtime, such as window handles (HWND), database connections, and so on. Therefore, you should provide both an explicit and an implicit way to free those resources. Provide implicit control by implementing the protected Finalize Method on an object (destructor syntax in C# and the Managed Extensions for C++). The garbage collector calls this method at some point after there are no longer any valid references to the object.
In some cases, you might want to provide programmers using an object with the ability to explicitly release these external resources before the garbage collector frees the object. If an external resource is scarce or expensive, better performance can be achieved if the programmer explicitly releases resources when they are no longer being used. To provide explicit control, implement the Dispose method provided by the IDisposable Interface. The consumer of the object should call this method when it is done using the object. Dispose can be called even if other references to the object are alive.
Note that even when you provide explicit control by way of Dispose, you should provide implicit cleanup using the Finalize method. Finalize provides a backup to prevent resources from permanently leaking if the programmer fails to call Dispose.
For more information about implementing Finalize and Dispose to clean up unmanaged resources, see Programming for Garbage Collection. The following code example illustrates the basic design pattern for implementing Dispose.
' Design pattern for a base class.
Public Class Base
' Implement IDisposable.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Protected Overloads Overridable Sub Dispose(disposing As Boolean)
If disposing Then
' Free other state (managed objects).
' Free your own state (unmanaged objects).
' Set large fields to null.
Protected Overrides Sub Finalize()
' Simply call Dispose(False).
' Design pattern for a derived class.
Public Class Derived
Protected Overloads Overrides Sub Dispose(disposing As Boolean)
If disposing Then
' Release managed resources.
' Release unmanaged resources.
' Set large fields to null.
' Call Dispose on your base class.
' The derived class does not have a Finalize method
' or a Dispose method with parameters because it inherits
' them from the base class.
// Design pattern for a base class.
public class Base: IDisposable
public void Dispose()
protected virtual void Dispose(bool disposing)
// Free other state (managed objects).
// Free your own state (unmanaged objects).
// Set large fields to null.
// Use C# destructor syntax for finalization code.
// Simply call Dispose(false).
// Design pattern for a derived class.
public class Derived: Base
protected override void Dispose(bool disposing)
// Release managed resources.
// Release unmanaged resources.
// Set large fields to null.
// Call Dispose on your base class.
// The derived class does not have a Finalize method
// or a Dispose method with parameters because it inherits
// them from the base class.
For a more detailed code example illustrating the design pattern for implementing Finalize and Dispose, see Implementing a Dispose Method.
Customizing a Dispose Method Name
Occasionally a domain-specific name is more appropriate than Dispose. For example, a file encapsulation might want to use the method name Close. In this case, implement Dispose privately and create a public Close method that calls Dispose. The following code example illustrates this pattern. You can replace Close with a method name appropriate to your domain.
' Do not make this method overridable.
' A derived class should not be allowed
' to override this method.
Public Sub Close()
' Call the Dispose method with no parameters.
// Do not make this method virtual.
// A derived class should not be allowed
// to override this method.
public void Close()
// Call the Dispose method with no parameters.
The following rules outline the usage guidelines for the Finalize method:
• Only implement Finalize on objects that require finalization. There are performance costs associated with Finalize methods.
• If you require a Finalize method, you should consider implementing IDisposable to allow users of your class to avoid the cost of invoking the Finalize method.
• Do not make the Finalize method more visible. It should be protected, not public.
• An object's Finalize method should free any external resources that the object owns. Moreover, a Finalize method should release only resources that are held onto by the object. The Finalize method should not reference any other objects.
• Do not directly call a Finalize method on an object other than the object's base class. This is not a valid operation in the C# programming language.
• Call the base.Finalize method from an object's Finalize method.
Note The base class's Finalize method is called automatically with the C# and the Managed Extensions for C++ destructor syntax.
The following rules outline the usage guidelines for the Dispose method:
• Implement the dispose design pattern on a type that encapsulates resources that explicitly need to be freed. Users can free external resources by calling the public Dispose method.
• Implement the dispose design pattern on a base type that commonly has derived types that hold on to resources, even if the base type does not. If the base type has a close method, often this indicates the need to implement Dispose. In such cases, do not implement a Finalize method on the base type. Finalize should be implemented in any derived types that introduce resources that require cleanup.
• Free any disposable resources a type owns in its Dispose method.
• After Dispose has been called on an instance, prevent the Finalize method from running by calling the GC.SuppressFinalize Method. The exception to this rule is the rare situation in which work must be done in Finalize that is not covered by Dispose.
• Call the base class's Dispose method if it implements IDisposable.
• Do not assume that Dispose will be called. Unmanaged resources owned by a type should also be released in a Finalize method in the event that Dispose is not called.
• Throw an ObjectDisposedException from instance methods on this type (other than Dispose) when resources are already disposed. This rule does not apply to the Dispose method because it should be callable multiple times without throwing an exception.
• Propagate the calls to Dispose through the hierarchy of base types. The Dispose method should free all resources held by this object and any object owned by this object. For example, you can create an object like a TextReader that holds onto a Stream and an Encoding, both of which are created by the TextReader without the user's knowledge. Furthermore, both the Stream and the Encoding can acquire external resources. When you call the Dispose method on the TextReader, it should in turn call Dispose on the Stream and the Encoding, causing them to release their external resources.
• You should consider not allowing an object to be usable after its Dispose method has been called. Recreating an object that has already been disposed is a difficult pattern to implement.
• Allow a Dispose method to be called more than once without throwing an exception. The method should do nothing after the first call.
Implementing the Equals Method
For related information on implementing the equality operator (==), see Guidelines for Implementing Equals and the Equality Operator (==).
• Override the GetHashCode method to allow a type to work correctly in a hash table.
• Do not throw an exception in the implementation of an Equals method. Instead, return false for a null argument.
• Follow the contract defined on the Object.Equals Method as follows:
• x.Equals(x) returns true.
• x.Equals(y) returns the same value as y.Equals(x).
• (x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.
• Successive invocations of x.Equals(y) return the same value as long as the objects referenced by x and y are not modified.
• x.Equals(null) returns false.
• For some kinds of objects, it is desirable to have Equals test for value equality instead of referential equality. Such implementations of Equals return true if the two objects have the same value, even if they are not the same instance. The definition of what constitutes an object's value is up to the implementer of the type, but it is typically some or all of the data stored in the instance variables of the object. For example, the value of a string is based on the characters of the string; the Equals method of the String class returns true for any two instances of a string that contain exactly the same characters in the same order.
• When the Equals method of a base class provides value equality, an override of Equals in a derived class should call the inherited implementation of Equals.
• If you are programming in a language that supports operator overloading, and you choose to overload the equality operator (==) for a specified type, that type should override the Equals method. Such implementations of the Equals method should return the same results as the equality operator. Following this guideline will help ensure that class library code using Equals (such as ArrayList and Hashtable) works in a manner that is consistent with the way the equality operator is used by application code.
• If you are implementing a value type, you should consider overriding the Equals method to gain increased performance over the default implementation of the Equals method on System.ValueType. If you override Equals and the language supports operator overloading, you should overload the equality operator for your value type.
• If you are implementing reference types, you should consider overriding the Equals method on a reference type if your type looks like a base type such as a Point, String, BigNumber, and so on. Most reference types should not overload the equality operator, even if they override Equals. However, if you are implementing a reference type that is intended to have value semantics, such as a complex number type, you should override the equality operator.
• If you implement the IComparable Interface on a given type, you should override Equals on that type.
Implementing the Equals method