Is it possible to pass parameters to a catch block?
Here is some example code:
try
{
myTextBox.Text = "Imagine, that could fail";
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
Can I pass the Textbox (myTextBox) now to my catch block if it would fail? smth. like that:
try
{
myTextBox.Text = "Imagine, that could fail";
}
catch (Exception e, TextBox textBox)
{
textBox.BorderBrush = Colors.Red;
MessageBox.Show(e.Message);
}
How I would do that?
No it's not possible by standart.
What you can do, is to define your custom exception and assign parameters there, for example:
public class MyCustomException : Exception
{
public string SomeAdditionalText {get;set;}
....
//any other properties
...
}
and inside the method which raises an exception raise your own MyCustomException
You only catch a single thing, which in C# must be an Exception. So not directly. However! If the Exception were, say, a custom SomethingSpecificException, then you could make that information available on e.SomeProperty.
public class SomethingSpecificException : Exception {
public Control SomeProperty {get;private set;}
public SomethingSpecificException(string message, Control control)
: base(message)
{
SomeProperty = control;
}
...
}
Then at some point you could:
throw new SomethingSpecificException("things went ill", ctrl);
and
catch(SomethingSpecificException ex) {
var ctrl = ex.SomeProperty;
....
}
don't know what you want to achieve, but in the catch block you can access any UI element, as you do in the try block. So for me there is no point of defining an additional parameter in the catch block.
Next to the possibility to use custom exception to distinguish what's going on:
try
{
myClass.DoSomethingThatCouldThrow();
myClass.DoSomethingThatThrowsSomethingElse();
myClass.DoAnotherThingWithAThirdExceptionType();
}
catch(FirstSpecialException ex)
{
// Do something if first fails...
}
catch(SecondSpecialException ex)
{
// Do something if second fails...
}
You could also put every statement into its own exception block. This would make your code quite lengthly, but is maybe the only possibility if you can't change the class to throw any special exception.
try
{
myClass.DoSomethingThatCouldThrow();
}
catch(InvalidOperationException ex)
{
// Do something if it fails...
}
try
{
myClass.DoSomethingThatCouldThrow();
}
catch(InvalidOperationException ex)
{
// Do something if it fails...
}
try
{
myClass.DoAnotherThingWithAThirdExceptionType();
}
catch(InvalidOperationException ex)
{
// Do something if it fails...
}
Due to the fact, that this last, looks a little bit like repetitive code, we could maybe put it into some method with the following body:
public void TryCatch<ExceptionT>(Action tryMethod, Action<ExceptionT> catchMethod)
where ExceptionT : Exception
{
// ToDo: ArgumentChecking!
try
{
tryMethod();
}
catch(ExceptionT ex)
{
catchMethod(ex);
}
}
Which could you then call with:
TryCatch<InvalidOperationException>(
() => myClass.DoSomething(),
(ex) => Console.WriteLine(ex.Message));
Related
I have the following methods in c#:
void Method1()
{
try
{
Method2();
}
catch(Method2Exception ex)
{
//Log error
}
}
void Method2()
{
if(error)
{
throw(new Method2Exception("error"));
}
//Do something and call method3
try
{
Method3();
}
catch(Method3Exception)
{
//??
}
}
void Method3()
{
//Do something
if(error)
{
throw(new Method3Exception("error"));
}
}
Method3 its gonna be call by different methods and it returns Method3Exception and I need rethrow the exception from Method2 to Method1 but I don't want catch Method3Exception on Method1. what's the best way to do that?
Any suggestions
The term (re)throw usally refer to throwing the exception back to the caller preserving the stack trace (which contains where the exception exactly occurred). This can be done using throw; without specifying the exception operand contrary to throw ex:
try
{
Method3();
}
catch(Method3Exception)
{
throw;
}
However, if you're just going to add a throw with nothing before it in that method. It is useless, just remove the try..catch and the exception is going to propagate to the caller which is the default behavior.
Docs:
A throw statement can be used in a catch block to re-throw the
exception that the catch block caught. In this case, the throw
statement does not take an exception operand.
Alternative way to re-throwing the exception (using throw; as described in other answers) is to wrap the exception in inner exception. As described in MSDN, all custom exceptions should have at least four constructors, and one of them is
public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }
So if all your custom exceptions are like this, you could wrap the exception from Method3 as inner exception:
void Method2()
{
if(error)
{
throw(new Method2Exception("error"));
}
//Do something and call method3
try
{
Method3();
}
catch(Method3Exception exc)
{
throw new Method2Exception("error", exc); // exc is passed as inner exception
}
}
Then if you want to inspect the inner exception in Method1, you can use property InnerException:
void Method1()
{
try
{
Method2();
}
catch(Method2Exception ex)
{
if(ex.InnerException != null)
{
var message = ex.InnerException.Message;
// Do what you need with the message
}
}
}
In Method2, you can throw a new Method2Exception with the existing Method3Exception as its InnerException:
try
{
Method3();
}
catch(Method3Exception method3Exception)
{
throw new Method2Exception("Message", method3Exception);
}
Then you can catch the Method2Exception above:
try
{
Method2();
}
catch(Method2Exception ex)
{
//Log error
}
Exceptions are bubbles up by default. For example,
void FirstMethod()
{
int a = 0;
int b = 10;
int c = b / a;
}
void SecondMethod()
{
FirstMethod();
}
void ThirdMethod()
{
SecondMethod();
}
void FourthMethod()
{
try
{
ThirdMethod();
}
catch (DivideByZeroException ex)
{
// Handle error
}
}
The exception will occur in FirstMethod and it will go upwards and will be cought at ForurthMethod. If you want to log the exception at ThirdMethod for example, but still want your exception to be handled at FourthMethod then you have to options:
First option:
void ThirdMethod()
{
try
{
SecondMethod();
}
catch (Exception ex)
{
// Log the error
throw; // Throw exception without affecting StackTrace
}
}
Second option:
After C# 6.0 you can do this with ease by using exception filters. Create a logger method which returns false.
bool Log(Exception ex)
{
// Log the error
return false;
}
Add exception filter in third method:
void ThirdMethod()
{
try
{
SecondMethod();
}
catch (Exception ex) when(Log(ex))
{
// Debugger won't reach here
}
}
I have a class which contains several methods.
One of the methods runs in a while loop (MainMethod).
I call out to helper methods in the same class from MainMethod.
The Try Catch is contained within MainMethod where most of the execution occurs.
If an exception occurs in a helper method which doesn't contain a Try Catch, will it be caught further up? i.e. inside MainMethod which called the helper method.
class Class1
{
public MainMethod()
{
while (true)
{
try
{
// ...
// ...
// ...
HelperMethod();
// ...
// ...
}
catch (Exception e)
{
// Console.WriteLine(e.ToString());
// logger.log(e.ToString();
// throw e;
// ...
}
}
}
public HelperMethod()
{
// No Try Catch
// if (today == "tuesday") program explodes.
}
}
Thanks.
Yes. If a method has no try/catch block it will "bubble up" the stack and be caught by the next handler up the chain. If there is no handler, that's when your program terminates because an exception was "unhandled".
Yes it will. Something like this:
public class Helper
{
public void SomeMethod()
{
throw new InvalidCastException("I don't like this cast.");
}
public void SomeOtherMethod()
{
throw new ArgumentException("Your argument is invalid.");
}
}
public class Caller
{
public void CallHelper()
{
try
{
new Helper().SomeMethod();
}
catch (ArgumentException exception)
{
// Do something there
}
catch (Exception exception)
{
// Do something here
}
try
{
new Helper().SomeOtherMethod();
}
catch (ArgumentException exception)
{
// Do something there
}
catch (Exception exception)
{
// Do something here
}
}
}
Note that if caller application handles that specific type of exception, specific catch block will be called.
IMHO, it is good to handle specific exceptions that may be thrown by methods you call from your code. However, that also means that author of method you are calling created a decent document sharing exceptions that we need to expect from his code.
Like in the question. I want to check if something on the collection of exceptions is my custom exception or is it the Exception class given by the .Net framework. Thnaks in advance for your help. \
Please note:
I don't know what is the class name of my custom exception it could be called exceptionA, exceptionB or for example xyzException
I have code like this:
public IEnumerable<Type> GetClassHierarchy(Type type)
{
if (type == null) yield break;
Type typeInHierarchy = type;
do
{
yield return typeInHierarchy;
typeInHierarchy = typeInHierarchy.BaseType;
}
while (typeInHierarchy != null && !typeInHierarchy.IsInterface);
}
public string GetException(System.Exception ex)
{
if (ex == null)
{
return null;
}
if (ex.InnerException == null)
{
return ex.Message;
}
var exceptionHerarchy = GetClassHierarchy(ex.GetType());
var isMyException = exceptionHerarchy.Any(t => t != typeof(System.Exception));
if (isMyException)
{
return string.Format("{0};{1}", ex.Message, GetException(ex.InnerException));
}
else
{
return GetException(ex.InnerException);
}
}
var isMyException = exceptionHerarchy.Any(t => t != typeof(System.Exception)); this is alays returning true because there is this type on the list probably
Very simple:
var t = myException.GetType().FullName;
bool isSystemException = (t.StartsWith("System."));
Exception types in the .NET Framework are all in System or one of its subnamespaces.
EDIT: To make this slightly prettier, create an extension function to the Exception class:
public static bool IsSystemException(this Exception exception)
{
return (exception.GetType().FullName.StartsWith("System."));
}
Double reconsider why do you want to do it. And then use one of the solutions below.
Better
Derive all custom exceptions from one base class exception provided by you and catch it in try-catch block.
Worse
Dynamically check some information about exception using Reflection, like its assembly:
ex.GetType().AssemblyQualifiedName
Make your Exception class extend from a custom base class.
class MyBaseEception : Exception
{
}
class MyCustomException : MyBaseException {}
try
{
}
catch (MyBaseException customException) {....}
catch (Exception e)
{
}
Although one wonders why you want to do this.
Heres my 2 pence...
try
{
}
catch (Exception e)
{
if (e.GetType().Assembly.GetName().Name != "My.Own.Namespace")
{
// this is a .net exception?
}
}
Why have custom exceptions if you're unsure when they would fire? IME, custom exceptions are typically used around business logic when you want to handle a specific case. Otherwise rely on the framework. In terms of the code, stack your custom exceptions first, then have a catch all in case the custom exception does not fire.
try
{
//do something
}
catch (MyCustomException ex)
{
//log, continue, throw, etc
}
catch (Exception e)
{
//log, continue, throw, etc
}
I've written a custom exception AbortTestException, which is pretty simple:
class AbortTestException : Exception
{
public AbortTestException(string message)
: base(message) { }
}
Then I have a function that will throw it:
class Foo
{
public void Throws()
{
throw new AbortTestException("hi");
}
}
And Throws() gets called via method reference:
class Program
{
static void Main(string[] args)
{
Type myType = (typeof(Foo));
var method = myType.GetMethod("Throws");
try
{
method.Invoke(new Foo(), null);
}
catch (AbortTestException ex)
{
Console.WriteLine("AbortTestException");
}
catch (Exception ex)
{
Console.WriteLine("Exception");
}
}
}
However, something weird happens. Even though Throws rises an AbortTestException, the catch(Exception) block gets used (instead of the catch(AbortTestException) block). I tried putting the "throw new AbortTestException("hi")" portion in the try block itself, and verified that the correct catch block is used.
Is there some reason an exception would be re-cast when emitted via MethodInfo.invoke()?
http://msdn.microsoft.com/en-us/library/4k9x6bc0.aspx
Per the MSDN a TargetInvocationException is thrown if the invoked method or constructor throws an exception.
Did you check the nested Exception? My guess the original exception (AbortTest...) is wrapped in a nested one. The nested Exception will be in the InnerException property of the one which is caught by your code
Remember that catching Exception will match any exception that isn't caught by a more specific catch block before it:
Type myType = (typeof(Foo));
var method = myType.GetMethod("Throws");
try
{
try
{
method.Invoke(new Foo(), null);
}
catch (AbortTestException ex)
{
Console.WriteLine("AbortTestException");
}
catch(TargetInvocationException tie)
{
throw tie.InnerException;
}
catch (Exception ex)
{
Console.WriteLine("Exception");
}
}
catch(AbortTestException ate)
{
Console.WriteLine("AbortTestException after re-throw from TargetInvocationException");
}
This is the skeleton of the code I have:
if(CheckForSomething())
{
try
{
//do something
}
catch (UnauthorizedAccessException ex)
{
LogException(ex, item.server);
}
catch (Exception ex)
{
LogException(ex, item.server);
}
}
else
{
string error = "Some error";
//want to call LogException with error as argument
}
private static void LogException(Exception ex)
{
//write ex to one log file
// write ex.message to another log file
}
How can I call LogException method from the else block? I tried casting string as exception and creating an exception.
A better question imo is not how but why you would want to do this? Why not define two LogError overloads, one that takes an Exception and another that takes a string.
private static void LogError(Exception ex)
{
// write ex to one log file
// write ex.message to another log file
}
private static void LogError(string error)
{
//nothing to write to exception-specific log file
// write error info to another log file
}
It's not really advisable to generate your own Exception instance just for logging like this.
LogException(new Exception("some error"));
Have you considered factoring the // write ex.message to another log file behavior into a separate function and calling that with your desired string?
if(CheckForSomething())
{
try
{
// do something
}
catch (UnauthorizedAccessException ex)
{
LogException(ex);
}
catch (Exception ex) // Never do this. Do you know how to handle an OutOfMemoryException?
{
LogException(ex);
}
}
else
{
string error = "Some error";
LogMessage(error);
}
private static void LogException(Exception ex)
{
// write ex to one log file
LogMessage(ex.Message);
}
private static void LogMessage(string message)
{
// write message to another log file
}
you can also make you own exception class like this:
public class LogException: Exception
{
public LogException() : base()
{
}
public LogException(string message) : base(message)
{
}
}
Exception e = new Exception(error);
LogException ee = new LogException (Exception e);
throw ee;
Put this in the else block
You can do something like previously mentioned
LogException(new Exception("some error"));
But it might be better to create your own exception class:
class MyException : Exception
{
//...
}
then
LogException(new MyException());
Some good solutions so far. You don't want to create a custom exception just for logging someone else will have a WTF? moment reading your code.
The alternative is to just extract the message from exception for the log.... something like
if(CheckForSomething())
{
try
{
// do something
}
catch (UnauthorizedAccessException ex)
{
LogMessage(ex.Message);
}
}
else
{
LogMessage("Some Error!");
}
private static void LogMessage(string message)
{
//write message to log
}
Creating an exception for the sole purpose of passing it into a format handled by a method is a hack. It breaks the implicit understanding among programmers as to what exceptions are and what they are used for.