Pros and Cons of implementing a generic custom exc

2019-06-28 06:00发布

问题:

What are the pros and cons of implementing a custom exception as follows:
Create an enum which represents error messages in its descriptions:

public class Enums
{
    public enum Errors
    {
        [Description("This is a test exception")]
        TestError,
        ...
    }
}

Create a custom exception class:

public class CustomException : ApplicationException
{
    protected Enums.Errors _customError;
    public CustomException(Enums.Errors customError)
    {
        this._customError = customError;
    }
    public override string Message
    {
        get
        {
            return this._customError!= Enums.Errors.Base ? this.customError.GetDescription() : base.Message;
        }
    }  
}  

The GetDescription method is an enum extension method which gets the enum description using reflection. This way, I can throw exception like:

throw new customException(enums.Errors.TestError);  

And show it to the user in catch block like:

Console.WriteLn(ex.Message);  

I've seen this approach recommended by an MVP. What are the benefits of this approach over the followings:

  • Using generic exception: throw new Exception("Error Message");.
  • Using Custom Exception: Define custom exceptions for any situation. e.g. (WebServiceException class, AuthenticationException class, etc.)

Here's the link to the recommendation by the MVP.

Thank you.

回答1:

Personally, i don't think it's a good idea.

You should always throw as specific exceptions as possible. The same goes for catching.

It's easy to decide if we want to catch a WebServiceException or AuthenticationException, but with your Enum-example, we have to parse a string to decide if we want to catch it or not. What happens if this message changes?

I don't think it has any benefits at all. For each error type, you have to create a new Enum member. Why not create a new class instead?



回答2:

The major advantage of custom exceptions is the language support for differentiation between different exception types. For example

try 
{
    SomeFunc()
}
catch( CustomException EX)
{
    //This is my error that I know how to fix
    FixThis()
    DoSomeAwesomeStuff()
}
catch( Exception exa)
{
    //Somthing else is wrong 
    WeepLikeBaby();
}

If I use the message Property

try 
{
    SomeFunc()
}
catch( Exception exa)
{
    if(exa.Message == "ErrType 1")
    {
        DoStuff;
    }
    if(exa.Message == "ErrType 2")
    { 
         Die();
     }
}

Utilizing The Base enum example can still retain this capability. However you give yourself one place to define your messages, but that is solved in a variety of different ways by applications. The enum example would make creating localized messages pretty simple as It will give you A way to define your message strings independently.

Another Advantage is that you can add Cusotm data that makes sense in you application. Say for example you have a customer information system, and the customer ID is almost always going to be important. If you utilize the message property only, every handler will have to know how to parse out that information if needed.

public class MyCustomeEx : Exception
{
    int CustID { get; set; }
}

public void Fail()
{ 
    //Awww Customer error
    throw new MyCustomeEx () {CustID = 123}
}


回答3:

Option 1 I would not recommend. You should not be throwing System.Exception at all. You should always throw the most specific exception available for your situation in order to have reasonably structured exception handling in your code.

The major drawback I see in your proposed method (Errors enum) is that there is no way you can decide if you want to handle or not the exception without catching it first. With custom exceptions you can make that decision beforehand.



回答4:

Please see my (accepted) answer at the following similar Stack Overflow question: Custom exception vs built in exception with very descriptive message. It should prove helpful in providing arguments against frivilous custom exceptions.



回答5:

The link to the MVP's recommendation was shared in comments.

After looking at the code and the question I think the reason for this is to limit the possible messages in the exception. And maybe help with localizing exception texts, but then there's extra work to do in this example. Anyways, such a method shouldn't be used for creating "Exception sub-types" that are processed differently.