2

I have made a component that throws Exception. I'm thinking if I should stick with standard throw new Exception or if I should create specific exceptions.

I also consider user-defined exception as not appealing when it throws exception from Remoting or WCF. if I use standard exception, the caller can receive the exception, if I made a user-defined exception, the caller won't be able to receive the specific exception unless the component's assembly is also deployed to client; however, the client can receive the exception from user-defined exceptions if one catches the user-defined exception from within Remoting and WCF and rethrows it as standard exception, which in turn defeats the purpose of user-defined exception.

When is adding user-defined exception not so useful?

[EDIT]

Sharing my thoughts, I think user-defined exception is a must(at least one) on a component, so when you unit test your own component, you will not receive false positives.

This produces false positives:

[Test]
public void Tag_is_missing()
{

    string message = "";

    try
    {
        // Arrange  
            // this will fail on *nix systems       
        MyComponentHelper.ParseXml("C:\A.XML");
    }
    catch(Exception ex)
    {
        // Act
        message = ex.InnerException.Message;
    }


    // Assert
    // How can we be sure that the word "not found" error is from 
    // xml parsing or if from file loading? Doing Pokemon exception handling
    // will lead to ambiguities
    Assert.IsTrue(message.Contains("not found"));

}

If you didn't made your own exception, your unit test might receive false positives, the "not found" string could be from your component or from other subsystems of your component. So there goes my case of when one should create user-defined exception.

This won't produce false positives:

[Test]
public void Tag_is_missing()
{

    string message = "";

    try
    {
        // Arrange     
        // this will fail on *nix systems        
        MyComponentHelper.ParseXml("C:\A.XML");
    }
    catch(XmlParsingException ex)
    {
        // Act
        message = ex.InnerException.Message;

        // Assert
        // And now we are more sure that the error didn't come from
        // program subsystem; in particular, file subsystem.
        Assert.IsTrue(message.Contains("not found"));
    }


}

What's left to ponder is when one should create very specific user-defined exceptions. For now, I'll settle first on having just one user-defined exception for my component, unit testings should not yield false positives.

Hao
  • 8,047
  • 18
  • 63
  • 92
  • Your code segment will catch all the exceptions thrown by ParseXml. So in case the xml has not been parsed, then how would you definitely know why the exception has occured. Do not use System.Exception. As for the unit testing part, if an exception is expected from the code segment then use ExpectedException attribute for the test method [http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.expectedexceptionattribute%28v=vs.80%29.aspx]. – Devendra D. Chavan Dec 28 '10 at 02:42
  • Generally, you should never throw Exception, but rather prefer one of the many standard derivatives provided by the BCL. In your particular example, FileNotFoundException would be a good candidate. – Dan Bryant Dec 28 '10 at 02:56
  • @Devendra: indeed, that's what I did say, for a more testable code, one should create a user-defined exception, so there's more ambiguity that could arise on catching errors. @Dan Bryant: that's what I'm trying to raise out, if one didn't made a user-defined exception, one might receive a false positive. In fact, the intent is to catch an exception of missing tag, but the Pokemon exception approach(i.e. sans user-defined exception) could fall to either "tag not found" or "file not found", since I do Pokemon exception approach, the assertion can produce false positives – Hao Dec 28 '10 at 06:11
  • in unit testing, if the test case is expected to throw an exception, then you need to use the ExpectedException attribute rather than using a try...catch block. Custom exception is not required in case you want to only create more testable code. – Devendra D. Chavan Dec 28 '10 at 06:33
  • @Devendra: Hmm.. that's a new one to me. I will check how to use that. Thanks! Just now, I noticed that the expectedMessage parameter on ExpectedExceptionAttribute is now obsolete. Anyway, I'll check where I can use that attribute – Hao Dec 28 '10 at 06:41

3 Answers3

2

Use custom exceptions when you feel that the standard exceptions (provided by .NET) do not give enough information about the exception condition. In this custom exception, you could provide properties that provide more information about the exception than just the message string.

The custom exception is only a wrapper around the system exception. The original exception information is found in the InnerException property of the custom exception.

The exception class can be designed as:


public class NewException : BaseException, ISerializable
{
    public NewException()
    {
        // Add implementation.
    }
    public NewException(string message)
    {
        // Add implementation.
    }
    public NewException(string message, Exception inner)
    {
        // Add implementation.
    }

    // This constructor is needed for serialization.
   protected NewException(SerializationInfo info, StreamingContext context)
   {
        // Add implementation.
   }
}

While throwing the custom exception, use:


try
{
   .....
}
catch(ArgumentNullException argumentNullException)
{
   throw new NewException("This is a custom exception message", argumentNullException);
}

Additionally, it is recommended that you catch the base System.Exception only in the top most control class. In the inner classes you should catch the specific exception types and use custom exception if required.

For more information refer:

Devendra D. Chavan
  • 8,871
  • 4
  • 31
  • 35
0

I think user-defined exceptions have only sense when this solve your problem in good way in internal project development.

Svisstack
  • 16,203
  • 6
  • 66
  • 100
0

Trapping for Exception is very generic, and could mask other unanticipated errors (as you've mentioned) by other areas of your component. Using properties or other messages is an option.

However, the approach that I've found works best is to throw one of the standard exceptions that's a subclass of Exception (eg. ArgumentOutOfRangeException); if those are not precise enough, and you need to throw something, make a subclass and throw that.

Also bear in mind that exceptions are for exceptional cases. Does it make sense to throw an exception, or would you be better served by returning some value (I don't mean an error code)?

ashes999
  • 9,925
  • 16
  • 73
  • 124