Search code examples
c#.netexceptionerror-handlingcustom-error-handling

Problem with handling exceptions, errors and return values


I need your advice. My source application become very.. expanded. And I have a little problem dealing with errors, exceptions etc..

For example I have "DatabaseProvider" class where are methods to contact with db. I have to deal with standard exceptions, invalid data form database (for example wrong email format), errors returned from database. All that stuff I need to return to the function which called DatabaseProvider's method, so that method will log this exception or error, and still working. So I can't throw exception.

And if that were not enough, I have to return (from DatabaseProvider) a value in most of cases or object or list of objects.

So I thought, maybe create a class "Response". And object of that class will be returned from every method in my app.

Sth like that:

public class Response
{
    public bool Error { get; set; }
    public string ErrorMessage { get; set; }        
    public bool DatabaseError { get; set; }
    public string DatabaseMessage { get; set; }

    public Exception ex { get; set; }
}

But how to return (for example) a list of self design objects in the same time?

Using "out" parameters are the solution? What is the best way (best practice)? I was searching about that, but all i found was how to deal with exceptions (only)..


Solution

  • I would've recommended implementing a custom Exception which you can throw and catch, rather than returning this information, since it seems very error-specific.

    However if you always want to attach certain meta information to returned results, you might implement a small vehicle class to wrap the results while carrying meta information:

    abstract class ResultWrapper
    {
        //meta info, such as error references/properties/flags/statistics
    
        public ResultWrapper([meta info])
        {
            //set meta info
        }
    }
    
    class ResultList<T> : ResultWrapper
    {
        public readonly List<T> resultList;
    
        //constructor for resultList, plus meta information for parent
        public ResultList(List<T> resultList, [additional args for meta info]) : base([meta info])
        {
            this.resultList = resultList;
        }
    }
    
    class SingleResult<T> : ResultWrapper
    {
        public readonly T result;
    
        //constructor similar to above
    }
    

    Edit: Based on your comments, you should definitely go with custom Exceptions which you can throw (possible wrapping cause Exceptions). As Petar said, these can be caught within the loop and processed there without halting execution of subsequent tasks. The language supports exception handling for good reasons - I would make use of it.

    Also, fyi in your pattern:

    public bool Error { get; set; }
    public string ErrorMessage { get; set; }
    

    there is no need for the bool. Just check for non-null on the error message/reference field