Showing posts with label Exceptions. Show all posts
Showing posts with label Exceptions. Show all posts

Thursday, December 16, 2010

Exception Template

Here's an Exception template that complies with all Code Analysis warnings and best practices:
Writing a custom exception couldn't be more straight forward.  However there are some things that are not obvious that can be useful to comply with.

The choice to write a custom exception usually follows the process of checking to see if an existing .NET framework exception adequately explains the issue with enough information.  DO NOT throw System.Exception or System.SystemException, that just reeks of rotten lazy coding.

If you're using the "All Rules" Code Analysis category in your project you'll be walked through a series of changes to comply.  These all make sense when you think about them. I'll walk through them below.  For the sake of expediency here's a template for a standard custom exception to save you the trouble of trying several times to resolve all warnings:


namespace MyNamespace
{
    using System;
    using System.Runtime.Serialization;

    /// <summary>
    /// A Custom exception ...
    /// </summary>
    [Serializable]
    public class CustomException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        public CustomException()
            : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        /// <param name="message">The message.</param>
        public CustomException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="innerException">The inner exception.</param>
        public CustomException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
        protected CustomException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
 

        /*
         * Use this when adding custom properties to an exception.
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("CustomProperty", CustomProperty);
        }
        */
        }
}


[Serializable]
This is good practice to allow exceptions to be saved in full when persisted, or sent over a communications channel. Although WCF requires that all top level exceptions be FaultExceptions, I believe you can use a serializable exception as an inner exception. Also consider implementing ISerializable.

Inherit from Exception.
There is no real benefit from having deep inheritance hierarchies of exceptions, and this is the recommendation of the Microsoft Framework Design Guidelines.  A good example of excellent use of Exception inheritance with good meaning are the System.IO.IOException types. This allows you to catch all IO related exceptions. Also the name should always be suffixed with "Exception" for clarity and consistency with other .NET framework exceptions.  Its better to have many specific custom exception types than a few overused types that dilute their meaning.  One last thing on this, don't bother deriving from ApplicationException, to quote Jeffrey Richter: "its a class that should not be part of the .NET framework. The original idea was that classes derived from SystemException would indicate CLR exceptions where non-CLR would derive from ApplicationException. However a lot of exception classes didn't follow this guideline...and it lost all meaning." Do not derive from any other exception other than Exception or SystemException (for more information see the Framework Design Guidelines chapter on exceptions).

Constructors.
Because constructors cannot be prescribed in a base-class the three exception constructors that are always expected to be present are the three shown above.  Your custom exception can be passed into .NET framework code and into other code that is consistent with the .NET framework. For this reason you should always have these three constructors available.

The last constructor is to ensure serialization is performed correctly. 

Don't go nuts on overloaded constructors rather prefer properties. 

Don't bother with error codes of any kind, this is what Exception types are for.

Another thing worth considering is using the System.Environment.FailFast method to ensure your process terminates quickly and as cleanly as possible.  In a no-win situation this is the best idea when there is an unhandled exception that leaves the application in an inconsistent state.

Don't be tempted to use custom exception types in "normal" program logic. Ie: catching a FileNotFoundException and then creating a file.  This will result in bad performing code.  Rather check and create (ie File.Exists method).

When making extensive use of logging, don't be caught out by thinking that logging means you don't need exceptions.  When writing reusable frameworks and toolkits, you cannot assume how someone will want to use your library. Log by all means, but throw an exception that the consumer can optionally catch and have the choice of attempting a recovery or failing the process.

Thursday, June 3, 2010

Delay signed assembly problem

If you are using delay signing feature in Visual Studio, to defer the signing of your assemblies. You quickly run into problems trying to reference them during development.  Delay signing is used when the private key is closely guarded and developers do not have access to it.  Only the public key is available to partially sign the assemblies.  The final signing of the assemblies with the matching private key is done usually during the build process.

When you reference a compiled binary that is only partially signed during development (you would not do this outside of a developer environment), you will get an exception as follows:

FileLoadException as unhandled.
Could not load file or assembly 'AssemblyAbc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b4571042c8aa084e' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)

To enable this reference in Development, you can skip the certificate verification process using the Sn.exe tool.
sn.exe -Vr *,b4571042c8aa084e

Run that command in the Visual Studio 2010 Command Line and thereafter the reference will work.
The Vr option signifies you wish to skip verification for this assembly. * signifies any user, and the hex value is the public key token of the partially signed assembly.

If you're running a 64-bit installation of Vista you'll need to use the sn.exe located at C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64\sn.exe