I have written a function that may throw various exceptions..
public class MyClass
{
private void Test(string param)
{
if (param.Length > 10)
throw new ArgumentException();
else if (param.Length > 20)
throw new OverflowException();
else if (string.IsNullOrWhiteSpace(param))
throw new ArgumentException();
else if (param.Length < 1)
throw new FormatException();
}
public void Call(string input)
{
try
{
Test(input);
}
catch (Exception ex)
{
HandleException(ex);
}
}
private void HandleException(Exception ex)
{
//Check if ex is of type ArgumentException
//ToDo..
//Check if ex is of type OverflowException
//ToDo...
//Check if ex is of type ArgumentException
//ToDo..
//Check if ex if of type FormatException
//ToDo..
}
}
Is it possible to have the HandleException(ex) private method so that i can handle all exceptions. Otherwise, I have to write separate exception blocks for each expcetions
private void HandleException(Exception ex)
{
if (ex is ArgumentException)
{
//ToDo..
}
else if (ex is OverflowException)
{
//ToDo..
}
else if (ex is FormatException)
{
//ToDo..
}
}
if the performance of "is vs as" is so important for you you can use this approach
private void HandleException(Exception ex)
{
ArgumentException argEx;
OverflowException ovfEx;
FormatException fmtEx;
if ((argEx = ex as ArgumentException) != null)
{
//ToDo..
}
else if ((ovfEx = ex as OverflowException) != null)
{
//ToDo..
}
else if ((fmtEx = ex as FormatException) != null)
{
//ToDo..
}
}
Related
How do I handle, invoke exceptions from the add function.
The external function will throw two different exceptions depending on the conditions.
I would like to handle each of these exceptions differently in main.
Thanks for helps.
My example code:
static void Main(string[] args)
{
try
{
add(0, 0);
}
catch(Exception ex)
{
if(Exception 1){
//...
}
if(Exception 2){
//...
}
}
}
public static int add (int a, int b)
{
int result = a + b;
if (result == 0)
{
throw new Exception("Exception 1");
}
if(result > 10)
{
throw new Exception("Exception 2");
}
return result;
}
You have to use the message you assign in the add method, and then check the condition inside the main or another place you want The code with a solution:
static void Main(string[] args)
{
try
{
add(0, 0);
}
catch (Exception ex)
{
Console.WriteLine("catch");
if (ex.Message == "Exception 1")
{
Console.WriteLine("1");
}
if (ex.Message == "Exception 2")
{
Console.WriteLine("2");
}
}
}
public static int add(int a, int b)
{
int result = a + b;
if (result == 0)
{
throw new Exception("Exception 1");
}
if (result > 10)
{
throw new Exception("Exception 2");
}
return result;
}
The method should return true if an "ArgumentNullException" is thrown and set "exceptionMessage" parameter to an exception message; otherwise the method should return false.
public static bool CatchArgumentNullException(object obj, out string exceptionMessage)
{
exceptionMessage = string.Empty;
try
{
if (obj is null)
{
throw new ArgumentNullException(exceptionMessage);
}
}
catch (Exception)
{
}
return false;
}
The method returns false. Why? How to return true?
Code corrected
public static bool CatchArgumentNullException(object obj, out string exceptionMessage)
{
exceptionMessage = string.Empty;
try
{
if ( obj is null )
throw new ArgumentNullException();
}
catch ( Exception ex )
{
exceptionMessage = ex.Message;
return true;
}
return false;
}
Test
object obj1 = null;
object obj2 = new object();
if ( CatchArgumentNullException(obj1, out var msg1) )
Console.WriteLine("obj1: " + msg1);
else
Console.WriteLine("obj1 is not null");
if ( CatchArgumentNullException(obj2, out var msg2) )
Console.WriteLine("obj2: " + msg2);
else
Console.WriteLine("obj2 is not null");
Output
obj1: La valeur ne peut pas être null. // The value can't be null.
obj2 is not null
Improvement
public static bool IsArgumentNull(object instance, string name, out string errorMessage)
{
errorMessage= string.Empty;
try
{
if ( instance is null )
throw new ArgumentNullException(name);
}
catch ( Exception ex )
{
errorMessage= ex.Message;
return true;
}
return false;
}
object obj1 = null;
object obj2 = new object();
if ( IsArgumentNull(obj1, nameof(obj1), out var msg1) )
Console.WriteLine(msg1);
else
Console.WriteLine("obj1 is not null");
if ( IsArgumentNull(obj2, nameof(obj2), out var msg2) )
Console.WriteLine(msg2);
else
Console.WriteLine("obj2 is not null");
The value can't be null.
Name of the parameter : obj1
obj2 is not null
Now this is a method that returns true if an object is null and we have a standard and localized system message including the variable name.
You need to add return in catch statement
You can change code as below depending if you only want to catch ArgumentNullException or all type of exceptions. Your current catch statement is for all kind of exceptions.
public static bool CatchArgumentNullException(object obj, out string exceptionMessage)
{
exceptionMessage = string.Empty;
try
{
if (obj is null)
{
throw new ArgumentNullException(exceptionMessage);
}
}
catch (ArgumentNullException ex)
{
return true;
}
catch (Exception e)
{
return true;
}
return false;
}
I'm unit testing code for an application and I'm confused on how to test try/catch exceptions. What would be a good approach for testing this method?
public static Exception Create<TException>(string format, params object[] args) where TException : Exception
{
var type = typeof(TException);
try
{
if (type == typeof(ArgumentOutOfRangeException))
{
return (TException)Activator.CreateInstance(type, String.Empty, String.Format(format, args));
}
if (type == typeof(ArgumentNullException))
{
var name = format;
return (TException)Activator.CreateInstance(type, String.Empty, Constants.Strings.ValueCannotBeNull.FormatWith(name));
}
return (TException)Activator.CreateInstance(type, String.Format(format, args));
}
catch (MissingMethodException)
{
try
{
return (TException)Activator.CreateInstance(type);
}
catch (MissingMethodException ex)
{
return new Exception(ParameterlessConstructorMissing.FormatWith(type), ex);
}
}
}
How would I adjust the following Invoke call so that it caters for methods that return void and non-void types?
At the moment ErrorHandlingComponent.Invoke expects a Func<T> as its first parameter. I've found that when I'm trying to pass it a void method, the compiler complains.
public static T Invoke<T>(Func<T> func, int tryCount, TimeSpan tryInterval)
{
if (tryCount < 1)
{
throw new ArgumentOutOfRangeException("tryCount");
}
while (true)
{
try
{
return func();
}
catch (Exception ex)
{
if (--tryCount > 0)
{
Thread.Sleep(tryInterval);
continue;
}
LogError(ex.ToString());
throw;
}
}
}
You can't. A Func delegate is designed so that it always returns something.
The easiest way would be to create an overload of the Invoke method that takes an Action delegate rather than a Func:
public static void Invoke(Action action, int tryCount, TimeSpan tryInterval)
{
if (tryCount < 1)
{
throw new ArgumentOutOfRangeException("tryCount");
}
while (true)
{
try
{
action();
return;
}
catch (Exception ex)
{
if (--tryCount > 0)
{
Thread.Sleep(tryInterval);
continue;
}
LogError(ex.ToString());
throw;
}
}
}
Sometime you need to run specific code on specific threads, for example winforms. To get the code running on the UI thread you need something like this :
this.BeginInvoke(new MethodInvoker(() =>
{
try
{
//code
}
catch(Exception ex)
{
HandleException(ex);
}
}
SynchornixationContext is another way to do the same thing.
Say that we know that we need to run specific code in the UI thread and we have a given way of handling the exceptions that are thrown on this UI thread(BeginInvoke is not blocking so exceptions will not be transfered). How could we create a method that makes the same thing but simplier like this :
RunOnUIThread(MyMethod);
The RunOnUIThread will contains mor or less the same code as the first example in this code.
Is it possible to create a method like this? And if so How?
You can write some nice extension methods like this
public static class ControlExtension
{
public static IAsyncResult BeginInvokeWithExceptionHandling(this Control control, Action method, Action<Exception> exceptionHandler)
{
if (control == null) throw new ArgumentNullException("control");
if (method == null) throw new ArgumentNullException("method");
if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler");
return control.BeginInvoke(new MethodInvoker(() =>
{
try
{
method();
}
catch (Exception ex)
{
exceptionHandler(ex);
}
}));
}
public static IAsyncResult BeginInvokeWithExceptionHandling<T>(this Control control, Delegate method, Action<Exception> exceptionHandler, params object[] args)
{
if (control == null) throw new ArgumentNullException("control");
if (method == null) throw new ArgumentNullException("method");
if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler");
return control.BeginInvoke(new MethodInvoker(() =>
{
try
{
method.DynamicInvoke(args);
}
catch (Exception ex)
{
exceptionHandler(ex);
}
}));
}
}
How to use:
private void HandleException(Exception ex)
{
}
private void MyMethod()
{
}
this.BeginInvokeWithExceptionHandling(MyMethod, HandleException);
Note: Due to Delegate.DynamicInvoke this may be little less performing, you can fix it with strong typed delegate. It is also worth noting that control.BeginInvoke is also internally using Delegate.DynamicInvoke if it can't find what the delegate type is.
public static void InvokeControlAction<t>(t cont, Action<t> action) where t : Control
{
if (cont.InvokeRequired)
{ cont.Invoke(new Action<t, Action<t>>(InvokeControlAction),
new object[] { cont, action }); }
else
{ action(cont); }
}
CodeProject Reference
I ended upp with this based on Sriram´s suggestion :
public static void SendToUIThread(Action method, bool UseExceptionHandling = true)
{
if (method == null)
throw new ArgumentNullException("method is missing");
_threadSyncContext.Send(new SendOrPostCallback(delegate(object state)
{
if (UseExceptionHandling)
{
try
{
method();
}
catch (Exception ex)
{
ErrorController.Instance.LogAndDisplayException(ex, true);
}
}
else
method();
}), null);
}
public static void PostOnUIThread(this Control control, Action method, bool UseExceptionHandling = true)
{
if (method == null)
throw new ArgumentNullException("method is missing");
if (control.InvokeRequired)
PostOnUIThread(method, UseExceptionHandling);
else
{
if (UseExceptionHandling)
{
try { method(); }
catch (Exception ex) { ErrorController.Instance.LogAndDisplayException(ex, true); }
}
else
method();
}
}