assume we have following peace of code in C#:
try{
....
try{
throw new Exception1("exception1");
}catch(Exception exception){
...
throw new Exception2("exception2");
}
}catch(Exception exception){
...
log(exception.message);
}
is it possible in log point(outer catch) to access exception1 object and log that one as well?
Here are two reasonable examples of what I think you are talking about. They illustrate what I was trying to describe in the comments as well as what #Jonesopolis describes.
First, my case. Say you are writing a utility that calls some lower-level service that may throw. You may want to describe the behavior of the utility in a way that the exceptions that may bubble up have more meaning to the caller. In this case, I've documented that my utility will throw an ApplicationException if there is a problem.
I do this from two places, the first one when I check some pre-conditions (that the path name is neither null or empty and that it is a valid file name (I'm assuming that there is an IsValidFileName function I can call)).
But the other place is that if I try to do the operation and it throws (I haven't checked that File.ReadAllLines actually ever throws an IOException, but I'm guessing it can). In this case, I don't want to burden my users with catching a possible IOException, instead, I translated it into an ApplicationException that I document. I wrap the IOException with a catch and throw of my ApplicationException, but I include the IOException as the inner exception so that debugging and tracking down other issues works. The code looks like:
public IEnumerable<string> AccessFile(string pathName)
{
if (string.IsNullOrEmpty(pathName) || !IsValidFileName(pathName))
{
throw new ApplicationException("Invalid Path Name");
}
try
{
var result = File.ReadAllLines(pathName);
return result;
}
catch (IOException ex)
{
throw new ApplicationException("Error Accessing File", ex);
}
}
It's that second parameter to the ApplicationException that sets up the inner exception. This pattern is very common.
The other example is what #Jonesopolis describes.
Here I have a work function doing something. My application architecture demands that I do logging at the level of whatever the DoSomethingImportant function is at. So, it catches any exceptions that get thrown at a lower level. However, that code wants to bubble up any exceptions to the DoSomethingImportant function's caller. Here, it just uses the throw keyword with no argument. That rethrows the current exception and lets it bubble through.
It's important to use throw; with no arguments, and not throw ex;. The former allows the existing exception to bubble up. The latter unwinds the stack at the catch site, and then throws a new exception, losing all the stack information that might point to the faulting location.
This is the typical code that I'm talking about. It's also a very common pattern:
public void DoSomethingImportant()
{
try
{
DoSomethingLowLevel();
}
catch (Exception ex)
{
GetLogger().Log(ex);
throw;
}
}
I'm logging different exceptions with the following method that accepts the exception as well as some context information string.
public void LogException(string notes, Exception e)
{
var properties = new Dictionary<string, string>()
{
{ "notes", notes }
};
telemetry.TrackException(e, properties);
}
The exceptions are reported correctly, but they are missing
The custom property "notes"
The call stack
is the exception actually thrown ? are you catching that exception? if you just do
client.TrackException( new Exception() );
there won't be a stack frames on some OS's / runtimes.
but if you do
try
{
throw new Exception();
}
catch (Exception e)
{
client.TrackException( e );
}
you will get a stack trace. something about the act of throwing the exception actually populates the underlying frame the sdk uses.
for your custom property, that should be showing up right away, although sometime's there's a lag between a new custom property being sent the first time, and when it shows up in metadata as a field to display. Also, you're limited to 200 distinct named custom properties, so if you've already sent 200 other properties, the "notes" field will just get thrown away.
in general for UWP / release / .net native, you should still have frames, they just won't be very readable, they'll be memory addresses, but there's still a stack of them, and if you have the pdb's, etc, you can reverse engineer what was where.
though the above looks like "catastrophic failure" exceptions that might not have stack frames available?
According to the design guideline the catching exception should start from more specification exception to System.Exception.
like :
try
{
}
catch(IOException IOEx)
{
}
catch(ArrayIndexOutOfRangeException AIE)
{
}
.....
catch(Exception ex)
{
}
I heard that CLR tracks the stack to trace the exception one by one to find the matching one(if an error occur).
As stack is "Last in first out" in nature won't CLR look in
reverse order ? ( i.e Exception .. ArrayIndexOutOfRangeException .. IOException)
No - the stack in this case is the call stack, so if it doesn't find a handler in the current method, it will move up the stack to look for a handler. Within a particular method however, handlers are tested in the order they are specified.
In dotNet a line throws an exception and is caught, how can I figure out which line in which file threw the exception? Seems relatively straightforward, but I can't figure it out...
You can only do it if you have debug symbols available.
catch(Exception ex) {
// check the ex.StackTrace property
}
If you want to debug such a situation in VS, you'd better just check Thrown checkbox for Common Language Runtime Exceptions in Exceptions dialog located in Debug menu. The debugger will break as soon as the exception is thrown, even if it's in a try block.
Personally, I just log the exception's ToString() return value. The whole stack trace is included. It's one line of code ... dead simple.
You could use the StackFrame Class:
try
{
...
...
}
catch(...)
{
StackFrame sf = new StackFrame(true);
int lineNumber = sf.GetFileLineNumber();
int colNumber = sf.GetFileColumnNumber();
string fileName = sf.GetFileName();
string methodName = sf.GetMethod().Name;
}
Well, in .NET you have whats called a FirstChanceException. These essentially are thrown before an exception is handled. There are two ways of looking at the issue that you're presenting here. One is from a debugging angle. If debugging you can just set your debugger to catch thrown exceptions from the Debug/Exceptions window. This is easier in an interactive context. IF you need to record this information from within a non-interactive context then I would do something similar to what CMS is talking about...
try
{
...
}
catch(Exception ex)
{
System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace(ex);
System.Diagnostics.StackFrame firstFrame = stackTrace.GetFrame[0];
Console.WriteLine(firstFrame.GetFileLineNumber);
...
}
The only difference here is that we get the entire Stack Trace, then go to the first frame, which is where the exception was originally thrown.
This question already has answers here:
Best practices for catching and re-throwing .NET exceptions
(11 answers)
Closed 9 years ago.
Is it better to do this:
try
{
...
}
catch (Exception ex)
{
...
throw;
}
Or this:
try
{
...
}
catch (Exception ex)
{
...
throw ex;
}
Do they do the same thing? Is one better than the other?
You should always use the following syntax to rethrow an exception. Else you'll stomp the stack trace:
throw;
If you print the trace resulting from throw ex, you'll see that it ends on that statement and not at the real source of the exception.
Basically, it should be deemed a criminal offense to use throw ex.
If there is a need to rethrow an exception that comes from somewhere else (AggregateException, TargetInvocationException) or perhaps another thread, you also shouldn't rethrow it directly. Rather there is the ExceptionDispatchInfo that preserves all the necessary information.
try
{
methodInfo.Invoke(...);
}
catch (System.Reflection.TargetInvocationException e)
{
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(e.InnerException).Throw();
throw; // just to inform the compiler that the flow never leaves the block
}
My preferences is to use
try
{
}
catch (Exception ex)
{
...
throw new Exception ("Add more context here", ex)
}
This preserves the original error, but it allows you to add more context, such as an object ID, a connection string, and stuff like that. Often my exception reporting tool will have five chained exceptions to report, each reporting more detail.
If you throw an exception without a variable (the first example) the stack trace will include the original method that threw the exception.
In the second example, the stack trace will be changed to reflect the current method.
Example:
static string ReadAFile(string fileName) {
string result = string.Empty;
try {
result = File.ReadAllLines(fileName);
} catch(Exception ex) {
throw; // This will show ReadAllLines in the stack trace
throw ex; // This will show ReadAFile in the stack trace
}
The first preserves the original stack trace of the exception, the second replaces it with the current location.
Therefore the first is by far the better.
I'll agree that most of the time you either want to do a plain throw, to preserve as much information as possible about what went wrong, or you want to throw a new exception that may contain that as an inner-exception, or not, depending on how likely you are to want to know about the inner events that caused it.
There is an exception though. There are several cases where a method will call into another method and a condition that causes an exception in the inner call should be considered the same exception on the outer call.
One example is a specialised collection implemented by using another collection. Let's say it's a DistinctList<T> that wraps a List<T>, but refuses duplicate items.
If someone called ICollection<T>.CopyTo on your collection class, it might just be a straight call to CopyTo on the inner collection (if say, all the custom logic only applied to adding to the collection, or setting it up). Now, the conditions in which that call would throw are exactly the same conditions in which your collection should throw to match the documentation of ICollection<T>.CopyTo.
Now, you could just not catch the exception at all, and let it pass through. Here though, the user gets an exception from List<T> when they were calling something on a DistinctList<T>. It is not the end of the world, but you may want to hide those implementation details.
Or you could do your own checking:
public CopyTo(T[] array, int arrayIndex)
{
if(array == null)
throw new ArgumentNullException("array");
if(arrayIndex < 0)
throw new ArgumentOutOfRangeException("arrayIndex", "Array Index must be zero or greater.");
if(Count > array.Length + arrayIndex)
throw new ArgumentException("Not enough room in array to copy elements starting at index given.");
_innerList.CopyTo(array, arrayIndex);
}
That's not the worse code because it's boilerplate and we can probably just copy it from some other implementation of CopyTo where it wasn't a simple pass-through and we had to implement it ourselves. Still, it's needlessly repeating the exact same checks that are going to be done in _innerList.CopyTo(array, arrayIndex), so the only thing it has added to our code is 6 lines where there could be a bug.
We could check and wrap:
public CopyTo(T[] array, int arrayIndex)
{
try
{
_innerList.CopyTo(array, arrayIndex);
}
catch(ArgumentNullException ane)
{
throw new ArgumentNullException("array", ane);
}
catch(ArgumentOutOfRangeException aore)
{
throw new ArgumentOutOfRangeException("Array Index must be zero or greater.", aore);
}
catch(ArgumentException ae)
{
throw new ArgumentException("Not enough room in array to copy elements starting at index given.", ae);
}
}
In terms of new code added that could potentially be buggy, this is even worse. And we don't gain a thing from the inner exceptions. If we pass a null array to this method and receive an ArgumentNullException, we're not going to learn anything by examining the inner exception and learning that a call to _innerList.CopyTo was passed a null array and threw an ArgumentNullException.
Here, we can do everything we want with:
public CopyTo(T[] array, int arrayIndex)
{
try
{
_innerList.CopyTo(array, arrayIndex);
}
catch(ArgumentException ae)
{
throw ae;
}
}
Every one of the exceptions that we expect to have to throw if the user calls it with incorrect arguments, will correctly be thrown by that rethrow. If there's a bug in the logic used here, it's in one of two lines - either we were wrong in deciding this was a case where this approach works, or we were wrong in having ArgumentException as the exception type looked for. It's the only two bugs that the catch block can possibly have.
Now. I still agree that most of the time you either want a plain throw; or you want to construct your own exception to more directly match the problem from the perspective of the method in question. There are cases like the above where rethrowing like this makes more sense, and there are plenty of other cases. E.g., to take a very different example, if an ATOM file reader implemented with a FileStream and an XmlTextReader receives a file error or invalid XML, then it will perhaps want to throw exactly the same exception it received from those classes, but it should look to the caller that it is AtomFileReader that is throwing a FileNotFoundException or XmlException, so they might be candidates for similarly rethrowing.
We can also combine the two:
public CopyTo(T[] array, int arrayIndex)
{
try
{
_innerList.CopyTo(array, arrayIndex);
}
catch(ArgumentException ae)
{
throw ae;
}
catch(Exception ex)
{
//we weren't expecting this, there must be a bug in our code that put
//us into an invalid state, and subsequently let this exception happen.
LogException(ex);
throw;
}
}
You should always use "throw;" to rethrow the exceptions in .NET,
Refer to the blog post Throw vs. Throw ex.
Basically, MSIL (CIL) has two instructions - "throw" and "rethrow" and C#'s "throw ex;" gets compiled into MSIL's "throw" and C#'s "throw;" - into MSIL "rethrow"! Basically I can see the reason why "throw ex" overrides the stack trace.
The first is better. If you try to debug the second and look at the call stack you won't see where the original exception came from. There are tricks to keep the call-stack intact (try search, it's been answered before) if you really need to rethrow.
I found that if the exception is thrown in the same method that it is caught, the stack trace is not preserved, for what it's worth.
void testExceptionHandling()
{
try
{
throw new ArithmeticException("illegal expression");
}
catch (Exception ex)
{
throw;
}
finally
{
System.Diagnostics.Debug.WriteLine("finally called.");
}
}
It depends. In a debug build, I want to see the original stack trace with as little effort as possible. In that case, "throw;" fits the bill.
In a release build, however, (a) I want to log the error with the original stack trace included, and once that's done, (b) refashion the error handling to make more sense to the user. Here "Throw Exception" makes sense. It's true that rethrowing the error discards the original stack trace, but a non-developer gets nothing out of seeing stack trace information, so it's okay to rethrow the error.
void TrySuspectMethod()
{
try
{
SuspectMethod();
}
#if DEBUG
catch
{
//Don't log error, let developer see
//original stack trace easily
throw;
#else
catch (Exception ex)
{
//Log error for developers and then
//throw a error with a user-oriented message
throw new Exception(String.Format
("Dear user, sorry but: {0}", ex.Message));
#endif
}
}
The way the question is worded, pitting "Throw:" vs. "Throw ex;" makes it a bit of a red herring. The real choice is between "Throw;" and "Throw Exception," where "Throw ex;" is an unlikely special case of "Throw Exception."