Search code examples
c#exceptionnaming-conventions

Is it a good idea to nest custom exceptions?


I have a class that can throw a very rare exception that is very particular to that class.

I want to create a custom exception for it, but I ponder about the best location for this class.

The way I see it, my 3 options are:

  • Nested
  • Same Namespace
  • Different Namespace
// Nested
namespace Cubusky.Collections.Generic
{
    public class ObserverSet<T>
    {
        public class NonexistentUnsubscriberException : Exception
        {
            // ...
        }
    }
}
// Same Namespace
namespace Cubusky.Collections.Generic
{
    public class ObserverSet<T>
    {
        // ...
    }

    public class NonexistentUnsubscriberException : Exception
    {
        // ...
    }
}
// Different Namespace
namespace Cubusky.Collections.Generic
{
    public class ObserverSet<T>
    {
        // ...
    }
}

namespace Cubusky
{
    public class NonexistentUnsubscriberException : Exception
    {
        // ...
    } 
}

Solution

  • From what I understand about your question, I would prefer the nested one. The advantages are for the nested approach:

    • Encapsulation: The exception is tightly coupled with the ObserverSet<T> class, making it clear that this exception is specific to this class.
    • Reduced Namespace Pollution: Keeps the namespace cleaner by not adding additional classes at the top level.

    However disadvantages for that are:

    • Accessibility: The nested exception might be less discoverable and harder to access from outside the ObserverSet<T> class.
    • Complexity: Can make the ObserverSet<T> class more complex and harder to read.

    On the other hand, one will also find pros and cons for the other two approaches.

    Same Namespace

    Advantages:

    • Clarity: The exception is still closely associated with the ObserverSet<T> class but is more accessible.
    • Discoverability: Easier to find and use the exception from other parts of the codebase.

    Disadvantages:

    • Namespace Pollution: Adds more classes to the namespace, which might clutter it if there are many such exceptions.
    • Loose Coupling: Slightly less clear that the exception is specific to ObserverSet<T> compared to the nested approach.

    Different Namespace

    Advantages:

    • Separation of Concerns: Keeps the exception separate from the class, which can be beneficial if the exception might be used by other classes in the future.
    • Namespace Organization: Can help in organizing exceptions in a dedicated namespace.

    Disadvantages:

    • Context Loss: It becomes less clear that the exception is specific to ObserverSet<T>.
    • Discoverability: Might be harder to find the exception when working with ObserverSet<T>.

    From what I understand, you should go with the nested approach. This is due to its uniqueness of this exception. However, if you have several unique exception or need this exception later on for a different class, one would find charm in the other two options as well.