|
I'm trying to get my head around a good way to set up exception management in a custom class, if I understand some of the advice in CP articles and elsewhere correctly then something like this setup is 'a' good way:
Simplified case: A class encapsulates a 2D array and has an UpperBound property that takes a an integer and returns the UpperBound of that dimension (since it does not expose the array directly).
Rather than the UpperBound property testing that the integer is either 0 or 1, I should put the call to the array GetUpperBound(dimension) method in a Try block and catch the exceptions that can be thrown by the array method, then re-throw the exception from the encapsulating class with the array exception as the inner exception parameter. Is that smart?
Then if another method in the class uses the UpperBound property (in the encapsulating class) it should catch and re-throw the exceptions created by the UpperBound method (again with the inner exception as a parmater), hence the exception the programmer recieves has a trail directly from the methods they called through whatever path was then followed and ending up with the base exception thrown by the encapculated array.
For example:
Public ReadOnly Property UpperBound(ByVal dimension As Integer) As Integer
Get
Try
Return Me._matrix.GetUpperBound(dimension)
Catch inex As IndexOutOfRangeException
Throw New IndexOutOfRangeException("The dimension you specified is out of range for this matrix object. Matrix objects have only two dimensions, 0 and 1. See the inner exception for more detail.", inex)
Catch ex As Exception
Throw
End Try
End Get
End Property
Then if I had another method in my class (call it Iterate for example) that needed the UpperBound of the rows (dimension = 0), say to use in a For loop, it would again do this in a Try block, call the UpperBound property and catch the exceptions thrown by the UpperBound property. So if somehow this latter method (Iterate) managed to make a call to UpperBound(2) then the programmer would see the Iterate method throw an IndexOutOfRange exception with the UpperBound exception as its inner exception and that in turn would have the array GertUpperBound exception as an inner exception.
Smart, dumb - other names? Advice?
Mike
|
|
|
|
|
As long as your catching the exception adds value, then it's fine for you to catch it, add detail and then pass it back up the chain. A big note, in your sample though, you catch and throw the general purpose exception for no reason - as you are only interested in the IndexOutOfRangeException , that's the only one you should be catching there.
|
|
|
|
|
Thanks, Pete. In terms of adding value I am assuming that an exception raised by a method that you didn't call is harder to trace / debug, whereas if you have the full history then it should start with the method you called and you can then trace back to where that call went and probably have a better idea of where it went wrong - i.e. there's no apparent direct benefit of what I am doing in this (and most) cases other than tracing exceptions.
Pete O'Hanlon wrote: in your sample though, you catch and throw the general purpose exception for no reason That's something I saw in one of the CP articles (I think I interpreted it from this one[^]). I had read into it that what I am doing is saying that if anything I wasn't expecting happens, just re-throw the same thing to ensure you don't lose it, i.e. it's a side effect of a Try block. Maybe I assumed that without it I would in effect be 'swallowing' all other exceptions, but maybe that only happens if I catch the general purpose one and then leave the catch block empty?
Does your comment mean that it is redundant - i.e. is that what would have happended anyway, even without that last catch statement?
Thanks,
Mike
|
|
|
|
|
Mike-MadBadger wrote: I had read into it that what I am doing is saying that if anything I wasn't
expecting happens, just re-throw the same thing to ensure you don't lose it,
i.e. it's a side effect of a Try block. Maybe I assumed that without it I would
in effect be 'swallowing' all other exceptions, but maybe that only happens if I
catch the general purpose one and then leave the catch block empty?
Actually, what I was referring to was don't bother catching it at all. When you catch and throw, without doing anything with the exception, it's a waste of time. So, in your case, all you needed to catch was the IndexOutOfRangeException . Any other exception is still going to show your method in the stack trace, so there is still context there for you to work with.
I hope that explains it better.
|
|
|
|