The inner-most exception in c# - c#

Is there a way to get the inner-most exception without using :
while (e.InnerException != null) e = e.InnerException;
I'm looking for something like e.MostInnerException.

To extend on Hans Kesting's comment, an extension method might come in handy:
public static Exception GetInnerMostException(this Exception e)
{
if (e == null)
return null;
while (e.InnerException != null)
e = e.InnerException;
return e;
}

Here is another answer that differs a bit: you can create an enumerator.
With
public static IEnumerable<Exception> EnumerateInnerExceptions(this Exception ex)
{
while (ex.InnerException != null)
{
yield return ex.InnerException;
ex = ex.InnerException;
}
}
You can do
try
{
throw new Exception("1", new Exception("2", new Exception("3", new Exception("4"))));
}
catch (Exception ex)
{
foreach (var ie in ex.EnumerateInnerExceptions())
{
Console.WriteLine(ie.Message);
}
}
So, technically, you are not longer using a while loop a visible way :)

Related

After scenario Cleanup in Specflow - try catch finally

I am try to clean up the scenario by capturing screenshots
The problem I face is when I try to see how many times "try catch finally" is executed..it's executed nearly 20 times after initial try-finally-it goes directly to catch
Here is my code
[AfterScenario]
public void CleanUp()
{
int aaa = 0;
try
{
if (ScenarioContext.Current.TestError != null)
{
//Taking screenshot
}
Console.WriteLine("try");
}
catch
{
Console.WriteLine("Catch");
if (Browser != null)
{
Browser.Dispose();
Browser = null;
}
return;
}
finally
{
Console.WriteLine("finally");
if (Browser != null)
{
Browser.Dispose();
Browser = null;
Console.WriteLine("finallya");
}
}
return;
}
try
finally
after this why it goes to Catch again? when I am doing some thing wrong here?

syntax error? maybe missing something

Having a syntax error that I can not find I think. e.CmsData is showing error along with e.Message.
Error states: only assignment, call, decrement, and the new object expressions can be used as a statement.
What am I missing?
private static void OnMessageReceived (object sender, MessageReceivedEventArgs e)
{
try
{
if (e == null)
return;
if (e.CmsData != null) e.CmsData;
if (!String.IsNullOrEmpty(e.Message))
(e.Message);
}
catch (Exception ex)
{ }
{
// logger.Error(" Exception " + ex);
// throw ex;
}
}
e.CmsData;
is not a valid statement, you need to do something with it, like
var x = e.CmsData;
The same goes for
(e.Message);
Accessing a property like you did is invalid
e.Cmsdata; // Invalid
Properties are just like variables but encapsulated.
You're referencing variables but not doing anything with them.
Try something like this
private static void OnMessageReceived (object sender, MessageReceivedEventArgs e)
{
try
{
if (e == null)
return;
(e.CmsData != null)
{
var data = e.CmsData;
//Do something with "data"
}
if (!String.IsNullOrEmpty(e.Message))
MessageBox.Show(e.Message);
}
catch (Exception ex)
{
// logger.Error(" Exception " + ex);
// throw ex;
}
}

Looking for an elegant way to get around "Cannot await in the body of a finally clause"

I have the following function:
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
SomeLegacySynchronousCode(session);
await m_sessionProvider.EndSessionAsync(session);
}
where EndSessionAsync logs and swallows any exception (like a good destructor).
The problem is that SomeLegacySynchronousCode may throw an exception and then the session leaks.
It is clear to me perfectly why the following code is illegal:
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
try
{
SomeLegacySynchronousCode(session);
}
finally
{
await m_sessionProvider.EndSessionAsync(session);
}
}
So, I am looking for an alternative that would be both correct and elegant.
Variant I
private async Task DoSomething(NamespaceConnectionInfo nci)
{
var session = await m_sessionProvider.GetSessionAsync(nci);
Exception exc = null;
try
{
SomeLegacySynchronousCode(session);
}
catch (Exception e)
{
exc = e;
}
await m_sessionProvider.EndSessionAsync(session);
if (exc != null)
{
// Wrap to preserve the original stack trace.
throw new AggregateException(exc);
}
}
Variant II
private Task DoSomething(NamespaceConnectionInfo nci)
{
return m_sessionProvider.GetSessionAsync(nci).ContinueWith(t =>
{
Task result = null;
try
{
SomeLegacySynchronousCode(t.Result);
}
finally
{
if (t.Exception == null)
{
result = m_sessionProvider.EndSessionAsync(t.Result);
}
}
return result;
}).Unwrap();
}
Neither are as elegant as the aforementioned illegal async/await version.
I am looking to improve over the two variants that I have proposed, because both are ugly, frankly.
Any ideas?
The commonly-accepted answer appears to be similar to your Variation 1:
You can move the logic outside of the catch block and rethrow the
exception after, if needed, by using ExceptionDispatchInfo.
static async Task f()
{
ExceptionDispatchInfo capturedException = null;
try
{
await TaskThatFails();
}
catch (MyException ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
if (capturedException != null)
{
await ExceptionHandler();
capturedException.Throw();
}
}
This way, when the caller inspects the exception's StackTrace
property, it still records where inside TaskThatFails it was thrown.

How to go from one exception handler to another?

The best way to explain my question is with the following pseudo-code:
try
{
//Do work
}
catch (SqlException ex)
{
if (ex.Number == -2)
{
debugLogSQLTimeout(ex);
}
else
{
//How to go to 'Exception' handler?
}
}
catch (Exception ex)
{
debugLogGeneralException(ex);
}
Exception ex = null;
try
{
//Do work
}
catch (SqlException sqlEx)
{
ex = sqlEx;
if (ex.Number == -2)
{
//..
}
else
{
//..
}
}
catch (Exception generalEx)
{
ex = generalEx;
}
finally()
{
if (ex != null) debugLogGeneralException(ex);
}
The first catch clause that matches is the only one that can possibly run on the same try block.
The best way I can think of to do what you're attempting is to include casts and conditionals in the more general type:
try
{
//Do work
}
catch (Exception ex)
{
var sqlEx = ex as SqlException;
if (sqlEx != null && sqlEx.Number == -2)
{
debugLogSQLTimeout(ex);
}
else
{
debugLogGeneralException(ex);
}
}
If you find yourself writing this over and over again throughout your data layer, at least take the time to encapsulate it in a method.
I do not believe there is any way to do this as the catch blocks are in different scopes. There's no way to re-throw without exiting the try block and no way to 'call' the final catch block because it's only triggered during an exception.
I would suggest the same as roman m above and just make the same call. Otherwise you have to do something really bad. Like the below crazy code which you should never ever use but i included because it does something like what you want.
In general I think what you are doing is controlling normal flow via exceptions which isn't recommended. If you are trying to track for timeouts, you should probably just handle that another way.
Note that you could do something like the code below with the insanity of a goto statement, but i included it so no one can forget what a bad idea this is. =)
void Main()
{
Madness(new NotImplementedException("1")); //our 'special' case we handle
Madness(new NotImplementedException("2")); //our 'special' case we don't handle
Madness(new Exception("2")); //some other error
}
void Madness(Exception e){
Exception myGlobalError;
try
{
throw e;
}
catch (NotImplementedException ex)
{
if (ex.Message.Equals("1"))
{
Console.WriteLine("handle special error");
}
else
{
myGlobalError = ex;
Console.WriteLine("going to our crazy handler");
goto badidea;
}
}
catch (Exception ex)
{
myGlobalError = ex;
Console.WriteLine("going to our crazy handler");
goto badidea;
}
return;
badidea:
try{
throw myGlobalError;
}
catch (Exception ex)
{
Console.WriteLine("this is crazy!");
}
}
// Define other methods and classes here

Throw and catch exception in same method

In my method that writes to a database, I handle errors as shown in the code below. In catch (DbUpdateException ex) I want to re-throw the exception and catch it in the last catch (Exception ex).
Is that possible and how to do that? Code below doesn't do that.
using (Entities context = new Entities())
{
try
{
context.Office.Add(office);
retVal = context.SaveChanges();
}
catch (DbUpdateException ex)
{
SqlException innerException = ex.GetBaseException() as SqlException;
if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
{
throw
new Exception("Error ocurred");
}
//This is momenty where exception is thrown.
else
{
throw ex;
}
}
catch (Exception ex)
{
throw
new Exception("Error");
}
}
The following would be better:
context.Office.Add(office);
retVal = context.SaveChanges();
Let the except bubble up. No need to catch stuff if all you are going to do is re-throw.
Note: throw ex; will reset the stack trace - you want to do throw; normally.
If you want to catch exceptions from other catches then they cannot be on the same level.
Your current code has this structure:
try
{
}
catch (...)
{
}
catch (...)
{
}
You need to change it to:
try
{
try
{
}
catch (...)
{
// throw X
}
}
catch (...)
{
// catch X here
}
But you should think very carefully if you really want/need this. It does not look like a productive error handling pattern.
And see this answer for the 4 different ways to (re)throw an exception and their consequences.
have you tried try nesting your try...catch blocks?
using (Entities context = new Entities())
{
try
{
try
{
context.Office.Add(office);
retVal = context.SaveChanges();
}
catch (DbUpdateException ex)
{
SqlException innerException = ex.GetBaseException() as SqlException;
if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
{
throw new Exception("Error ocurred");
}
//This is momenty where exception is thrown.
else
{
throw ex;
}
}
}
catch (Exception ex)
{
throw new Exception("Error");
}
}
A try-catch processes only one catch block and they are evaluated in order. Therefore, if you really need this functionality you'll need to put a try-catch inside of a try-catch, like this:
using (Entities context = new Entities())
{
try
{
try
{
context.Office.Add(office);
retVal = context.SaveChanges();
}
catch (DbUpdateException ex)
{
SqlException innerException = ex.GetBaseException() as SqlException;
if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
{
throw
new Exception("Error ocurred");
}
//This is momenty where exception is thrown.
else
{
throw ex;
}
}
}
catch (Exception ex)
{
throw
new Exception("Error");
}
}
Try this:
void YourMethod()
{
using (Entities context = new Entities())
{
try
{
context.Office.Add(office);
retVal = context.SaveChanges();
}
catch (DbUpdateException ex)
{
SqlException innerException = ex.GetBaseException() as SqlException;
if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
{
throw
new Exception("Error ocurred");
}
//This is momenty where exception is thrown.
else
{
throw ex;
}
}
}
}
Then when you call your method enclose it with try catch block
try
{
YourMethod()
}
catch (Exception ex)
{
throw
new Exception("Error");
}
When you plan to nest your try-catch-block as described by "paul" be aware of the exception type:
using (Entities context = new Entities())
{
try
{
try
{
context.Office.Add(office);
retVal = context.SaveChanges();
}
catch (DbUpdateException ex)
{
SqlException innerException = ex.GetBaseException() as SqlException;
if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
{
// this exception will be catched too in outer try-catch block <--------
throw new Exception("Error ocurred");
}
//This is momenty where exception is thrown.
else
{
throw ex;
}
}
}
// Catch (DbUpdateException ex) if you plan to have the rethrown exception to be catched <------------
catch (Exception ex)
{
throw new Exception("Error");
}
}

Categories

Resources