What are industry standard best practices for implementing custom exceptions in C#?
Asked Answered
I

4

85

What are industry standard best practices for implementing custom exceptions in C#?

I have checked Google and there's a great number of recommendations, however I don't know which ones hold more credibility.

If anybody has any links to authoritative articles, that would also be helpful.

Italic answered 25/1, 2011 at 9:35 Comment(4)
Similar to bit.ly/hVTSgp I would recommend that you narrow your topic by further explaining what you're looking for.Varlet
My boss wants me to create a custom exception class for a program I have written so that we can easily identify specific errors. It will be things like: No data in a specific excel cell, outofrange exceptions (could use the standard for this), data not uploaded in a specific order, etc.Italic
Sounds like you're using exceptions to handle business logic flow - expected issues should be dealt with without the use of exceptions where possible.Lyra
@ck - I think you are probably right to be honest. I am going back through my code now and trying to change them to be handled differently. Thanks.Italic
B
71

The standard for creating custom exceptions is to derive from Exception. You can then introduce your own properties/methods and overloaded constructors (if applicable).

Here is a basic example of a custom ConnectionFailedException which takes in an extra parameter which is specific to the type of exception.

[Serializable]
public class ConnectionFailedException : Exception
{
    public ConnectionFailedException(string message, string connectionString)
        : base(message)
    {
        ConnectionString = connectionString;
    }

    public string ConnectionString { get; private set; }
}

In the application this could be used in scenarios where the application is attempting to connect to a database e.g.

try
{
    ConnectToDb(AConnString);
}
catch (Exception ex)
{
    throw new ConnectionFailedException(ex.Message, AConnString);
}

It's up to you to then handle the ConnectionFailedException at a higher level (if applicable)

Also have a look at Designing Custom Exceptions and Custom Exceptions

Bonnard answered 25/1, 2011 at 10:9 Comment(9)
Why not catching only the exceptions of type ConnectionFailedException more purposeful?Packston
@Anar the example shows how you raise the ConnectionFailedException the expectation is you would catch this higher up the call stack. You could catch a more meaningful exception raised from ConnectToDb rather than a general Exception, however, it was just for demonstration purposes.Bonnard
You mean it could have been ConnectionFailedException and it is not the point, right?Packston
@Anar sorry I am not sure I understand what it is you are trying to ask?Bonnard
Sorry for that. Let me ask it this way. Would it make a difference if we catched ConnectionFailedException instead of Exception?Packston
@Anar that's my point, the ConnectionFailedException is the custom exception you are introducing. The ConnectToDb method is assumed to be connecting to an external data store e.g. SQL Server/MySQL etc. therefore won't throw ConnectionFailedException. Instead it would most likely throw a vendor-specific exception e.g. SqlException. Obviously it would be better to catch the more specific exception, however, since the example is database-agnostic we just catch Exception.Bonnard
Eek.. chain your exceptions kids. The first parameter should be the connectionString and the second should be the entire ex aka innerException.Packard
@SalmanAbbas "here is a basic example..." - keywords being "basic" and "example".Bonnard
This implementation does not have serialization constructor. See the correct sample: https://mcmap.net/q/100055/-make-a-custom-net-exception-serializableEmbrey
V
15

Here is the code to create a custom exception:

using System;
using System.Runtime.Serialization;

namespace YourNamespaceHere
{
    [Serializable()]
    public class YourCustomException : Exception, ISerializable
    {
        public YourCustomException() : base() { }
        public YourCustomException(string message) : base(message) { }
        public YourCustomException(string message, System.Exception inner) : base(message, inner) { }
        public YourCustomException(SerializationInfo info, StreamingContext context) : base(info, context) { }
    }
}

See also: http://www.capprime.com/software_development_weblog/2005/06/16/CreatingACustomExceptionClassInC.aspx

Vacationist answered 14/8, 2012 at 15:20 Comment(3)
FWIW - this is almost exactly what comes out of using the Exception snippet included in Visual Studio.Jinn
Excellent. I wrote the blog post in 2005, but I think there was some guidance from Microsoft that I based it on and it looks like that guidance got codified into VS via a snippet.Vacationist
You don't need the impelments ISerializable on your class (Exception already implements it and you are inheriting from it) and your last (4th) constructor can be protected (it is protected on Exception).Colony
B
9

I assume you are looking for exception handling practices. So have look on following articles,

http://msdn.microsoft.com/en-us/library/ms229014.aspx //gives overall ideas about exceptions including custom exceptions

Braddy answered 25/1, 2011 at 9:48 Comment(0)
C
1

I use Custom Exceptions to communicate the nature of the error.

For example, I like using the framework provided "ArgumentNullException" to check arguments. Then later, when I see this error either in the debugger, or in an error log, I immediately know the nature of the error without reading any further.

The other end of the spectrum is the InvalidOperationException which could mean pretty much anything.

The alternative to custom exceptions is detailed error messages. That's ok, but by making a custom exception such as ConnectionFailed is more meaningful. Then the message itself can give greater details.

When creating such custom exceptions, I do not add any new properties. The reason for this is that if you have an error logger, you want it to work on all exceptions. If you add a special property, then the error logger is going to ignore it. For example, if you use MSTest, when you run your test and it fails, the custom properties are not displayed. But if you stick with the Message property of the baseclass, it will display just fine.

So the subclassing is very simple:

public class NavigationException : Exception{
    public NavigationException() {}
    public NavigationException(string msg) : base(msg) {}
    public NavigationException(string msg, Exception inner) : base(msg, inner) {}
}

This is very straightforward, works with any error logger, and when I see it, I know it was a Navigation problem and I can view the details if needed.

Greg

Cauterant answered 7/8, 2013 at 19:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.