How to override Catch(Exception) in Parent (Caller) method? - c#

Is there any way to force that the caller could override the catch ?
i.e.
void ParentMethod()
{
try
{
child_method();
}
catch(Exception e)
{
MessageBox.Show("parent");
}
}
void child_method()
{
try
{
smth();
}
catch(Exception e)
{
MessageBox.Show("child");
}
}
so, when smth throws exception, instead of "child", i could override that catch with parent, and show i.e. parent.
Note 1: I am in a case, where I don't control child. However, for the sake of the answer completion, you can still answer for the case when child is controlled.
Note 2: I nowhere mentioned that I have classes or inheritance. Please avoid answers for virtual/override things. I know that.

If the child method's code is also owned/controlled/has access to, by the person/group who owns/controls the code for parent method, then you can do few things -
if there's always a parent method to call this child method and that, child method is not going to be on its own (by your design), you can ignore the try-catch in child and have the parent handle whatever they want to.
If (not #1) then its true from the above comment.
Ideally, and this is purely from my experience and opinion, if a method needs try-catch (based on what it does would qualify for it), catch block should catch the exception, do something like log it, and throw unless thats the last calling method.

There's not a way to enforce that a called method must rethrow any raised exceptions. The calling method is free to swallow whatever exception it wants.
That said, the way to catch the exception in the parent method also is to either rethrow the original exception or a new exception:
void child_method()
{
try
{
smth();
}
catch(Exception e)
{
MessageBox.Show("child");
//or: throw new Exception("Exception thrown in child");
}
}

Short answer is no.
But there I guess you misunderstood few things about Object Oriented Programming.
So you can override a method with another method with same name and different prototype if you want more configuration or different behaviour.
You can inherite from a class and override methods to share a common part and adjust whatever you want.
Ok so there you want a common part parent that would contain the try catch section.
So there you got a really different approach from what you did, but if I understood well quite suite what you want.
using System;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
VirtualTest test1 = new Test1();
test1.ParentMethod();
VirtualTest test2 = new Test1();
test2.ParentMethod();
Console.ReadKey();
}
}
abstract class VirtualTest
{
public void ParentMethod()
{
try
{
ChildMethod();
}
catch
{
Console.WriteLine("parent");
}
}
protected abstract void ChildMethod();
}
class Test1 : VirtualTest
{
protected override void ChildMethod()
{
try
{
throw new ArgumentException("A message");
}
catch (ArgumentException e)
{
Console.WriteLine(e.Message);
throw; //Here is a way to handle more specificly some
//errors but still throwing and keeping the original stacktrace
}
}
}
class Test2 : VirtualTest
{
protected override void ChildMethod()
{
throw new NotImplementedException();
}
}
}
In that case you also have more control of what you're catching at which level and you can decide wether you want to deal with it or not.
The finer level you handle the Exception the better.
Also in that example Parents are actually parents and Children are actually childrend in a POO way.

Related

Confusing behaviour when handling exceptions in combination with using

Question
I am currently implementing a UOW pattern and have come upon a weird behaviour for exception handling, which is hindering my progress.
My UOW structure looks the following:
public abstract class UnitOfWork : IDisposable {
public virtual void Save() {
if (_madeAction) ThrowInvalidCall();
_madeAction = true;
}
public virtual void Cancel() {
if (_madeAction) ThrowInvalidCall();
_madeAction = true;
}
public virtual void Dispose() {
if (!_madeAction) {
Cancel();
throw new UnitOfWorkAborted("Unit of work was aborted and automatically rolled back!");
}
}
private bool _madeAction = false;
private void ThrowInvalidCall() => throw new InvalidOperationException($"{nameof(Save)} or {nameof(Cancel)} can only be called once in a unit of work!");
}
[Serializable]
public class UnitOfWorkAborted : Exception {
public UnitOfWorkAborted() { }
public UnitOfWorkAborted(string message) : base(message) { }
public UnitOfWorkAborted(string message, Exception inner) : base(message, inner) { }
}
public interface IUnitOfWorkFactory {
UnitOfWork CreateNew();
}
I am expecting to use this UOW as follows:
try {
using (var uow = uowFactory.CreateNew()) {
// Do some operation
throw new InvalidCastException(); // Oh, something went wrong.
uow.Save();
}
} catch (UnitOfWorkAborted ex) {
// Handle exception
}
The problem obviously is, that the excpetion will never be handled by my try/catch clause as it only handles UnitOfWorkAborted which is only thrown after the InvalidCastException.
My question is, is there any way I can use my UOW how I expect it to work? (I'd like to replicate this behaviour -> TransactionScope)
I want to keep the code for creating a UOW and managing it as simple as possible.
If possible, I would love to even have the actual exception as the inner exception of UnitOfWorkAborted.
Observations/Attempts
1. Instead of catching the UnitOfWorkAborted I can catch all Exceptions and cast it to UnitOfWorkAborted.
try {
using (var uow = uowFactory.CreateNew()) {
throw new InvalidCastException();
uow.Save();
}
} catch (Exception ex) {
UnitOfWorkAborted uowEx = ex as UnitOfWorkAborted;
if (uowEx is null) throw ex;
// Handle exception
}
Cons:
I will need to cast the exception to UnitOfWorkAborted and this adds code that should be avoidable because:
What is try/catch then even for when not for specifying which exception to handle? This approach just feels.. ugh.
2. Add a catch clause for Exception.
try {
using (var uow = uowFactory.CreateNew()) {
throw new InvalidCastException();
uow.Save();
}
} catch (UnitOfWorkAborted ex) {
// Handle exception
} catch (Exception ex) {
throw ex;
}
I discovered this through experimentation, it works perfectly fine. Would it be possible to get a side-explanation on the details for why this works, I would be incredibly interested to know. Either way, the syntax is incredibly misleading, even worse than with the first attempt, and this is no option of course, just, look at it.
Are these two attempts really my only options on solving this problem?
I ended up using the callback method suggested by Jeremy Lakeman in the comments, which ended up working perfectly fine, with the bonus of catching inner exceptions.

Attribute to suppress certain types of exceptions?

Is there any attribute that I can use, attached to the method definition, that will suppress any exceptions of a certain type originating in that method? e.g.
[SuppressException(typeof(TimeoutException))]
public void TroubleMethod()
{
}
So when there is a TimeoutException, it won't throw outside of TroubleMethod?
You can use exception handling around the entire method:
public void TroubleMethod()
{
try {
// ...
} catch(TimeoutException) {
// Throw away
}
}
I don't think an attribute that does what you describe exists, though. If you want the debugger to step through your method, you can always use [System.Diagnostics.DebuggerStepThrough()], but as for suppressing exceptions, I don't think that's possible.
You can use PostSharp to do some tricky instrumentation to add such attribute.
If you really want to do this, you can get a bit closer to your attribute-like syntax with:
static void SuppressException<TException>(Action a) where TException : Exception
{
try
{
a();
}
catch (TException) { }
}
public void TroubleMethod()
{
SuppressException<TimeoutException>(() => {
...
}
}
Not that I am aware of, but you can always do this:
public void TroubleMethod()
{
try
{
// silly code goes here
}
catch() { }
}
A bad idea in almost all circumstances, though sometimes acceptable (rare). Just make sure to leave a comment for future maintainers (this includes you).
you could use try-catch to catch the exeptions and just ignore it or better you could respond to that exeption
check out the reference

Checking constraints using IDisposable -- madness or genius?

I ran across a pattern in a codebase I'm working on today that initially seemed extremely clever, then later drove me insane, and now I'm wondering if there's a way to rescue the clever part while minimizing the insanity.
We have a bunch of objects that implement IContractObject, and a class InvariantChecker that looks like this:
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public void Dispose()
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
internal class Foo : IContractObject
{
private int DoWork()
{
using (new InvariantChecker(this))
{
// do some stuff
}
// when the Dispose() method is called here, we'll throw if the work we
// did invalidated our state somehow
}
}
This is used to provide a relatively painless runtime validation of state consistency. I didn't write this, but it initially seemed like a pretty cool idea.
However, the problem arises if Foo.DoWork throws an exception. When the exception is thrown, it's likely that we're in an inconsistent state, which means that the InvariantChecker also throws, hiding the original exception. This may happen several times as the exception propagates up the call stack, with an InvariantChecker at each frame hiding the exception from the frame below. In order to diagnose the problem, I had to disable the throw in the InvariantChecker, and only then could I see the original exception.
This is obviously terrible. However, is there any way to rescue the cleverness of the original idea without getting the awful exception-hiding behavior?
I don't like the idea of overloading the meaning of using in this way. Why not have a static method which takes a delegate type instead? So you'd write:
InvariantChecker.Check(this, () =>
{
// do some stuff
});
Or even better, just make it an extension method:
this.CheckInvariantActions(() =>
{
// do some stuff
});
(Note that the "this" part is needed in order to get the C# compiler to look for extension methods that are applicable to this.) This also allows you to use a "normal" method to implement the action, if you want, and use a method group conversion to create a delegate for it. You might also want to allow it to return a value if you would sometimes want to return from the body.
Now CheckInvariantActions can use something like:
action();
if (!target.CheckInvariants())
{
throw new ContractViolatedException();
}
I would also suggest that CheckInvariants should probably throw the exception directly, rather than just returning bool - that way the exception can give information about which invariant was violated.
This is a horrid abuse of the using pattern. The using pattern is for disposing of unmanaged resources, not for "clever" tricks like this. I suggest just writing straight forward code.
If you really want to do this:
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public void Dispose()
{
if (Marshal.GetExceptionCode() != 0xCCCCCCCC && obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
Instead of this:
using (new InvariantChecker(this)) {
// do some stuff
}
Just do this (assuming you don't return from do some stuff):
// do some stuff
this.EnforceInvariants();
If you need to return from do some stuff, I believe some refactoring is in order:
DoSomeStuff(); // returns void
this.EnforceInvariants();
...
var result = DoSomeStuff(); // returns non-void
this.EnforceInvariants();
return result;
It's simpler and you won't have the problems you were having before.
You just need a simple extension method:
public static class InvariantEnforcer {
public static void EnforceInvariants(this IContractObject obj) {
if (!obj.CheckInvariants()) {
throw new ContractViolatedException();
}
}
}
Add a property to the InvariantChecker class that allows you to suppress the check/throw.
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public bool Suppress { get; set; }
public void Dispose()
{
if (!this.Suppress)
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
}
internal class Foo : IContractObject
{
private int DoWork()
{
using (var checker = new InvariantChecker(this))
{
try
{
// do some stuff
}
catch
{
checker.Suppress = true;
throw;
}
}
}
}
If you current problem is to get original exception - go to Debug -> Exceptions and check "thrown" for all CLR exceptions. It will break when exception is thrown and as result you'll see it first. You may need to also turn off tools->options->debug->"my code only" option if exceptions are throw from "not your code" from VS point of view.
What is needed to make this nice is a clean means of finding out whether an exception is pending when Dispose is called. Either Microsoft should provide a standardized means of finding out at any time what exception (if any) will be pending when the current try-finally block exits, or Microsoft should support an extended Dispose interface (perhaps DisposeEx, which would inherit Dispose) which would accept a pending-exception parameter.

What is the best way to re-use exception handling logic in C#?

I have two functions that have different enough logic but pretty much the same exception handling:
public void DoIt1 // DoIt2 has different logic but same exception handling
{
try
... DoIt1 logic
catch (MySpecialException myEx)
{
Debug.WriteLine(myEx.MyErrorString);
throw;
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
throw;
}
}
It is not possible to use a single entry point for DoIt1 and DoIt2, because they are called in from outside.
Is Copy/Pase (for the exception block) the best approach?
It depends... if there is that much commonality, you could pass in the thing to do as a parameter - either as an interface or a delegate:
void Foo(Action thingToDo) {
if(thingToDo == null) throw new ArgumentNullException("thingToDo");
try {
thingToDo();
} catch {...} // lots of
}
And call as:
Foo(delegate { /* logic A */ });
Foo(delegate { /* logic B */ });
Try:
public static class Catching<TException> where TException : Exception
{
public static bool Try<T>(Func<T> func, out T result)
{
try
{
result = func();
return true;
}
catch (TException x)
{
// log exception message (with call stacks
// and all InnerExceptions)
}
result = default(T);
return false;
}
public static T Try<T>(Func<T> func, T defaultValue)
{
T result;
if (Try(func, out result))
return result;
return defaultValue;
}
}
Example:
int queueSize = Catching<MyParsingException>
.Try(() => Parse(optionStr, "QueueSize"), 5);
If Parse throws a MyParsingException, queueSize will default to 5, otherwise the returned value from Parse is used (or any other exception will propagate normally, which is usually what you want with an unexpected exception).
This helps to avoid breaking up the flow of the code, and also centralises your logging policy.
You can write specialised versions of this kind of exception wrapping for special cases, e.g. catching a particular set of three exceptions, or whatever.
For the extreme end of the spectrum of possible solutions, check out Aspect-Oriented-Programming techniques, and tools such as PostSharp or Microsoft Policy Injection Block. This way you can define an aspect that does something on exception and weave it into all places in your code that need it.
If you just want to log the exceptions' messages and items, without doing special processing in the catch block, you could create a Reflection-based Object logger, passing the Exception as an argument. Doing so, you don't have a lot of catch blocks.
And if you are the code's owner, you can put the logging procedure inside the MySpecialException's constructor, removing the catch's block and making the code cleaner.
You could have something like:
public static class ErrorHandler
{
public static void HandleMyException(MyException myEx)
{
Debug.WriteLine(myEx.MyErrorString);
throw;
}
public static void HandleException(Exception myEx)
{
Debug.WriteLine(e.ToString());
throw;
}
}
or, in this specific case, have a more generic function like:
public static class ErrorHandler
{
public static void WriteAndThrow(string msg)
{
Debug.WriteLine(msg);
throw;
}
}

How to get the method call history?

I am trying to get the list of calls made from the beginning of a try block to the exception. In the code below, when I fall into the Catch block, the StackTrace in the Exception object is the following :
at ConsoleApplication.Program.MethodC() / at
ConsoleApplication.Program.Main(String[] args).
This is totally expected, but doesn't help me to get the history of calls. Does anybody have an idea on how I could do this?
static void MethodA() { }
static void MethodB() { }
static void MethodC() { throw new Exception(); }
static void Main(string[] args)
{
try
{
MethodA();
MethodB();
MethodC();
}
catch (Exception e)
{
// Get list of calls
throw;
}
}
I was surprised to see that the StackTrace property of the Exception object isn't StackTrace object. Is there any reason for this?
In the end, the purpose of all this is simple. If an exception is thrown during the execution of the code, I want to look at the meta data (attribute) of each of the methods called.
As I understand your question, you want to be able to know which methods was called before MethodC in your try block. I don't think you can do that without adding code to your methods.
When MethodA finishes executing, it is no longer on the stack, so there is nowhere you can get the information from. Same goes for MethodB, and only MethodC is on the stack when the Exception occurs.
It seems you're not going to be able to get a stack trace for each method called with the try block unless you add custom logging code to each method. However, you can create a System.Diagnostics.StackTrace option easily from an exception simply by passing the Exception object to the constructor. This will make available all the information about the stack trace including whether the exception was thrown from MethodA/MethodB/MethodC, which might be at least somewhat helpful to you.
Example code:
static void MethodA() { }
static void MethodB() { }
static void MethodC() { throw new Exception(); }
static void Main(string[] args)
{
try
{
MethodA();
MethodB();
MethodC();
}
catch (Exception e)
{
System.Diagnostics.StackTrace callStack = new System.Diagnostics.StackTrace(e);
System.Diagnostics.StackFrame frame = null;
System.Reflection.MethodBase calledMethod = null;
System.Reflection.ParameterInfo[] passedParams = null;
for (int x = 0; x < callStack.FrameCount; x++)
{
callStack.GetFrame(x);
calledMethod = frame.GetMethod();
passedParams = calledMethod.GetParameters();
foreach (System.Reflection.ParameterInfo param in passedParams)
System.Console.WriteLine(param.ToString());
}
}
}
(You can see this SO thread for the original answer containing the code. I've just slightly modified it.)
Hope that's at least a partial solution to your question.
You can easily get a StackTrace object from anywhere in your code but as has already been pointed out you can not get the full history of method calls.

Categories

Resources