简体   繁体   中英

Same type exception from different places

Let's say you have two different libraries that you write for different format of files. One parses type A of file and one parses type B. Now I see that in most cases most folks say that the exceptions already defined (let's say we use C# and .NET) are enough to handle most situations. In this case I think that is OK that in both cases we if we encounter some problems when parsing we throw a InvalidDataException that tells us that the format is not correct.What happens when we must catch both exceptions in a higher level function that must do something with them?

void SomeHigherFunction()
{
    try
    {
        int x = GetSomeDataFromFileA();  // throws InvalidDataException
        int y = GetSomeDataFromFileB();  // throws InvalidDataException
    }
    catch(InvalidDataException)   // what failed ? 
    {
         ShowMessageWithWhatFileFailed()  // what display ?
    }
}

How do we know where the code failed? Should in this case be two different Exception types defined, one TypeAException and one TypeBException or is something easy here that I miss? I don't want to wrap each function and return a bool with the result. In this case I would wrap function A in a function and let it return true if successful and execute B further. But that is clearly a bad design and wrong use of exceptions. Should I just create new types in this cases ? Or how?

You can use Exception.Data Collection to pass the owner of the Exception and do something with it further.

I refactored your example a little, but i think this fits your requirements:

class Program
{
    [Serializable]
    public abstract class Parser
    {
        public int GetData()
        {
            bool error = true;
            if (error)
            {
                InvalidDataException exception = new InvalidDataException();
                exception.Data.Add("owner", this);
                throw exception;
            }
            return 0;
        }

        public abstract void handleError();
    }
    [Serializable]
    private class ParserA : Parser
    {
        public override void handleError()
        {
            Console.WriteLine("Handled in A");
        }
    }
    [Serializable]
    private class ParserB : Parser
    {
        public override void handleError()
        {
            Console.WriteLine("Handled in B");
        }
    }
    static void Main(String[] args)
    {
        try
        {
            int x = new ParserA().GetData();
            int y = new ParserB().GetData();
        }
        catch (InvalidDataException ex)
        {
            Parser parser = ex.Data["owner"] as Parser;
            if(parser != null)
                parser.handleError();

            // or even this if you prefer:
            if (parser is ParserA)
                Console.WriteLine("A");
        }
    }
}

In a real case scenario GetData method would be virtual, but you got the idea

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM