Exceptions exist for a reason – use them!

C# and all CLR-compliant languages support a fantastic facility to ensuring code quality. That facility is the Exception. Sadly, it is an often under-utilized facility. How many times have you seen code that checks for an object’s validity? If, like me, you are part of the “Fail Early” school, then the Exception Class is your best friend. By fail early, I mean that as soon as possible, without any interaction from my code or any additional code, the system will abend. Of course, if your classes can throw exceptions, it means that your code will have to handle exceptions. Bear in mind that the try…catch block does come with an overhead cost that *may* impair performance. The key to look at is is what value are you getting for that cost? And – is whatever performance penalty there may be managed and negligible to the user.

It’s not enough to throw exceptions. Rather, you need to throw the right exception and in many cases, you’ll need to throw a custom exception. With a specific exception, you have a better chance of ascertaining exactly what happened. Only as a last resort will you want this:

   throw new Exception("Some other, unaccounted for exception");

Note: when possible, use the built-in exceptions that are already in .NET. For more detail on the base exceptions in .NET, refer to this link: http://msdn.microsoft.com/en-us/library/z4c5tckx(v=vs.110).aspx

Often you may want to create a custom exception:

    public class MyCustomException : Exception
    {
        public MyCustomException() : base("My Custom Exception")
        {

        }
    }

It’s worth noting in the constructor, you get access to many properties – some of which you may want to initialize:

Practical Exampleexception_image1

The following is an example of an approach that you may wish to follow and adapt as necessary:

    public abstract class MyBaseException : Exception
    {
        public  MyBaseException(string message) : base(message)
        {
            HelpLink = "http://www.myhelplink.com/helptext";
            
        }

        public override string ToString()
        {

            return string.Format("{0}{1}{2}{3}", 
                base.ToString(),Environment.NewLine,
                "For more help on this error: ",HelpLink);

        }

        public void Log()
        {
            Console.WriteLine(ToString());
        }
    }

Note: In this particular example, no need to worry about serialization as there are no custom properties.

One of the nice things about the base Exception Class is that it has a usable ToString() method. Nevertheless, it is missing some additional information that could be useful. This is why there is an override for the ToString() method.

With a base exception class in place:

 try
            {
               throw new MyCustomException("My Custom Message");
            }
            catch (MyCustomException ex)
            {
                ex.Log();
            }

Here is the output:

exception_image2

Hopefully, this post has given you some ideas on how you can effectively use exceptions in your applications.

About johnvpetersen

I've been developing software for 20 years, starting with dBase, Clipper and FoxBase + thereafter, migrating to FoxPro and Visual FoxPro and Visual Basic. Other areas of concentration include Oracle and SQL Server - versions 6-2008. From 1995 to 2001, I was a Microsoft Visual FoxPro MVP. Today, my emphasis is on ASP MVC .NET applications. I am a current Microsoft ASP .NET MVP. Publishing In 1999, I wrote the definitive whitepaper on ADO for VFP Developers. In 2002, I wrote the Absolute Beginner’s Guide to Databases for Que Publishing. I was a co-author of Visual FoxPro Enterprise Development from Prima Publishing with Rod Paddock, Ron Talmadge and Eric Ranft. I was also a co-author of Visual Basic Web Development from Prima Publishing with Rod Paddock and Richard Campbell. Education - B.S Business Administration – Mansfield University - M.B.A. – Information Systems – Saint Joseph’s University - J.D. – Rutgers University School of Law (Camden) In 2004, I graduated from the Rutgers University School of Law with a Juris Doctor Degree. I passed the Pennsylvania and New Jersey Bar exams and was in private practice for several years – concentrating transactional and general business law (contracts, copyrights, trademarks, independent contractor agreements, NDA’s, intellectual property and mergers and acquisitions.).
This entry was posted in C#, Exceptions. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • johnvpetersen

    Thanks for catching that Mike!! I had the original code fixed but never updated the post. Done.

  • MikeScott8

    just a minor thing but in your override of ToString you have the “return” of the formatted string, and then the original “return” just just calls the base ToString. looks like you forgot to remove the auto generated return line
    :)

  • johnvpetersen

    Glad you found value. Thanks for your feedback.

  • johnvpetersen

    Resharper from JetBrains. Check out http://www.jetbrains.com/resharper/

  • George McCormick

    Thanks John. This is a good starting point in getting me to think about how I should handle exceptions.

  • Peter Malík

    What plugin or something overrrides your intellisense icons ? Thanks

  • johnvpetersen

    The log method is just an example of adding functionality. It’s rather passive. Regardless of approach, people may always elect to stray to bad practices or avoid good practices. The point of the post is to highlight exceptions have a place and that the base implementation can be extended.

    Thanks for your comment.

  • http://stackoverflow.com/users/76337/john-saunders John Saunders

    Further to the comments from Fran Knebels, I want to point out that your use of a Log method may encourage readers to follow the invalid pattern of try/catch/log/ignore.

  • johnvpetersen

    Thanks for the comment. A few things. First, your point about leveraging the existing built-in exceptions is a good one. I’ve updated the post to reflect that and to point to a useful MSDN article. Second, as to serialization, the basic custom class I created doesn’t have custom properties. Therefore, I didn’t need to worry about that. Nevertheless, you did allude to point worth mentioning about serialization. Keep in mind YAGNI. Until you need to worry about it, don’t worry about it until you need it. Certainly plan for it – but wait to implement. Finally, as to your assertion that one should *never* throw an exception is on its face, an invalid assertion. The better guidance is to throw exceptions when appropriate. I did mention that try catches are expensive and that when electing that construct, one has to be aware of, calculate and consider the value proposition of that choice. Looking at your example, I don’t think you needed to worry about it as well. _someData is a private member. Why would you have to worry about serializing that particular piece of data? If it was a public member, sure, I’ll buy that. Last word – I’m not going to get get involved in a protracted back and forth. I think your points and my points are clear. Thanks.

  • Fran Knebels

    Your recommendations goes against almost all the recommendations of the people who designed the CLR. First don’t create custom exceptions for the sake of having a custom exception. In your example all you are doing in your custom exception is setting the Message and HelpLink properties, why introduce a new class when every exception already has this information? If you were creating an exception with custom information i.e. new properties that actually extend the Exception class, then by all means, create new exception. The CLR has a number of pre-packaged exceptions that are good for almost any situation.

    Second your exception class design doesn’t take into account serialization concerns. Here’s a custom exceptions example

    using System;

    using System.Runtime.Serialization;

    using System.Security.Permissions;

    namespace Scratch

    {

    [Serializable]

    public class CustomException : Exception, ISerializable

    {

    private const String SOME_DATA = “_someData”;

    private String _someData;

    public CustomException();

    public CustomException(String message) : base(message) { }

    public CustomException(String message, String someData) : base(message) { _someData = someData; }
    public CustomException(String message, Exception innerException) : base(message, innerException) { }

    protected CustomException(SerializationInfo info, StreamingContext context) : base(info, context)

    {

    if (info != null)

    {

    this._someData = info.GetString(SOME_DATA);

    }

    }

    [SecurityPermission(SecurityAction.Demand, SerializationFormatter =true)]

    public override void GetObjectData(SerializationInfo info, StreamingContext context)

    {

    base.GetObjectData(info, context);

    if (info != null)

    info.AddValue(SOME_DATA, _someData);

    }

    }

    }

    Third. Never throw Exception. All system exceptions even OutOfMemoryException, ExecutionEngineException, StackOverflowException, …. derive from Exception so if you throw Exception you’re going to have to catch and Exception which may or may not be the Exception you anticipated. Always catch the most specific exception you can. Also if you catch Exception, you may be swallowing errors that should be reported back to users/testers so that the underlying error can be fixed.