4

I have these two methods I am working on. One saves and one loads. Obviously both need some sort of error handling so I have implemented some "catch all handling". Now the heel of the hunt is, what happens next is contextual to where, during runtime, the error occurs. Because of this I would like to handle the error in the caller, one level above. That way I can have different logic for different situations.

An example would be. If I check the load on first run and it fails I can assume that they memory may have been cleared. But if I try to load during execution I can assume the memory wasn't cleared (by correct means) and something must be up.

    public void SaveToStorage(AccountCollection Collection)
    {
        try
        {
            var storage = IsolatedStorageSettings.ApplicationSettings;
            storage["defaultCollection"] = Collection;
            storage.Save();
        }
        catch (Exception ex)
        {
            // Do something meaningful here
        }
    }

    public AccountCollection LoadFromStorage()
    {
        try
        {
            AccountCollection collection;
            var storage = IsolatedStorageSettings.ApplicationSettings;
            storage.TryGetValue("defaultCollection", out collection);
            return collection;
        }
        catch (Exception ex)
        {
          // Do something meaningful here
        }

        return null;
    }

Essentially I am asking can I throw the error up to the caller but still retain the original error details.

EDIT: Both John and Andrew having given correct answers. Andrew will get the green tick as I would like to do some other generic clean up in the original class.

deanvmc
  • 5,957
  • 6
  • 38
  • 68

7 Answers7

11

To all the negative remarks about not catching, he stated he wanted to do some unwinding in the method that the exception is thrown, but also continue it up the stack so other methods can perform something. He isn't catching the exception just to throw it again, he wants to perform some action, then throw it again.

catch (Exception ex)
{
    // Do something
    throw;
}

Edit

For some reason I read this as C++, so removed my remarks about copying the exception.

Andrew T Finnell
  • 13,417
  • 3
  • 33
  • 49
  • 8
    `throw` on its own retains all the information including the stack trace. I'm pretty sure (but not 100%) that `throw ex` will throw the exception but you lose the stack information. – Jonathon Bolster Jan 06 '11 at 16:14
  • 1
    Yes thats correct. With `throw` you keep the stack information. WIth `throw ex` or `throw new Exception` you loose that information. – Jan Jan 06 '11 at 16:19
  • @Jonathon fixed. Understanding he wants to keep the original stack instead of creating a new one. – Andrew T Finnell Jan 06 '11 at 16:19
  • Cheers! I will just use throw then! – deanvmc Jan 06 '11 at 16:20
  • @Jan: There's a trap for anyone coming from Java, where `throw ex` will preserve the exception object unchanged, including the stack trace. – Lawrence Dol Jan 07 '11 at 03:35
6

If you don't catch the exception, it will propagate upwards.

That's how it works. Do not put try/catch blocks everywhere. Only put them where you are going to actually handle the exception.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
4

If the only thing you want to do is rethrow the exception then it's better to not even have a try/catch since it will propagate upwards but if you want to do something and rethrow then you need this:

catch(Exception ex)
{
    // Do your bit with ex

    throw;
}

By using just throw, you retain all information about the exception including the stack trace.

http://winterdom.com/2002/09/rethrowingexceptionsinc

Jonathon Bolster
  • 15,811
  • 3
  • 43
  • 46
2

This example from MSDN sounds like what you might be looking for.

This example catches the original exception, takes according action (in this case writing a line to console), then creates and throws a new exception which contains the original.

class TestTryCatch
{
    static int GetInt(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch (System.IndexOutOfRangeException e)  // CS0168
        {
            System.Console.WriteLine(e.Message);
            //set IndexOutOfRangeException to the new exception's InnerException
            throw new System.ArgumentOutOfRangeException("index parameter is out of range.", e);
        }
    }
}

http://msdn.microsoft.com/en-us/library/ms173165(v=vs.80).aspx

Robb
  • 3,801
  • 1
  • 34
  • 37
1

This is typically achieved by wrapping the catched exception in a new one via the InnerException Property. That way you can send more meaningful details and the original exception to the caller:

catch(Exception ex)
{
    // Do something...
    throw new MyOwnDataStorageException("message", ex);
}

Or you can do just nothing and the exception will propagate automatically to the caller with the full callstack.

Jan
  • 15,802
  • 5
  • 35
  • 59
0

If you cant do anything useful when you cant catch the expection in AccountCollection() then let it bubble up to the calling method and handle it there.

diagonalbatman
  • 17,340
  • 3
  • 31
  • 31
-2

You could just throw the original exception (in your current code available as ex) within your catch block. It really depends on if you'd like to do any exception handling within those functions. If you don't want to, put the try/catch blocks outside (place them in the caller where you'd like to handle the exception(s)).

Mario
  • 35,726
  • 5
  • 62
  • 78