Out of scope C # re-throw exception

I am fully aware that what I'm going to ask is not good practice ... but:

Let's say I have a class containing a function in which I want to always return a value, but keep any exceptions that may arise for later processing. Sort of:

public Exception _error { get; set; } public bool IsValid() { try { //do something here to cause exception return true; } catch (Exception ex) { _error = ex; return false; } } 

Now that I have saved the exception, is it possible to exclude the exception from the external method altogether, preserving both the original stack trace and the type of exception?

 throw _error; //lose stack trace throw new Exception("", _error) //lose type 

Thanks for watching or responding.

EDIT:

Thanks to some additional points, I understand that the idea below only takes information and does not actually add or simplify the situation. Thanks again to everyone.

After thinking about Peter's answers and comments, I now wonder if the Exception class can make a partial solution as shown below. This overrides as many exceptions as possible so that the New exception looks like its innerexception, including stacktrace .. dirty I know, but interesting:

 public class ExceptionWrapper : Exception { private Exception _innerException; public ExceptionWrapper(Exception ex) : base("", ex) { _innerException = ex; this.Source = ex.Source; this.HelpLink = ex.HelpLink; } public override string StackTrace { get { return _innerException.StackTrace; } } public override System.Collections.IDictionary Data { get { return _innerException.Data; } } public override string Message { get { return _innerException.Message; } } public new Exception InnerException { get { return _innerException.InnerException; } } } 

Strike>

+4
source share
3 answers

No, It is Immpossible.

However, you usually solve this by wrapping the exception in the new exception:

 throw new MyException("Wrapper", _error); 

This supports the _error stack _error , but you get a new exception. Your solution in the second example is the correct way to handle these cases.

+7
source

Consider using a reflex to create a shell exception for the correct type ( Activator.CreateInstance ) and calling the constructor, which will accept the internal exception that you saved.

For instance:

 [Test] public void test() { Exception ex = new ArgumentNullException(); Exception wrapped = (Exception)Activator. CreateInstance(ex.GetType(), "wrapped", ex); Type expectedType = typeof(ArgumentNullException); Assert.IsInstanceOf(expectedType, wrapped, "Is ArgumentNullException."); Assert.AreEqual(ex, wrapped.InnerException, "Exception is wrapped."); } 

Update

To reduce the problem with the constructor, you can consider using the default constructor (should be there for the exception that follows the design recommendations, but not necessary), and then update the new instance by setting its fields through reflection.

I agree that the approach is strongly " meh ", but rather a study of the idea. I would not recommend it.

Design guidelines for exceptions require a default constructor, so this behavior can continue in the framework somewhere anyway. Perhaps for some fuzzy serialization / deserialization of exceptions across some communication boundary?

+2
source

It seems that .net-4.5 has added a new API to grab stack / exception information and reorganize them in different contexts. This is called ExceptionDispatchInfo . This is useful if you need to indirectly control the control of running tasks, for example, if you perform manual thread control for tasks or if the Task does not meet your needs. In your example, it should look like this:

 public ExceptionDispatchInfo _error { get; private set; } public bool IsValid() { try { //do something here to cause exception return true; } catch (Exception ex) { _error = ExceptionDispatchInfo.Capture(ex); return false; } } /// <summary>Throw underlying exception if invalid.</summary> public void AssertWasValid() => _error?.Throw(); 

Now it does not save the original caller. The displayed stack trace shows the calls from the original try block to the code there, the statement that violates the original and new parts of the stack, and then the calls to ExceptionDispatchInfo.Throw() as the new part of the displayed stack. This is similar to what traces with async code look like. If you care about the original caller, it doesn't seem to work. But if you want the line / method to throw an exception, that should be enough.

+1
source

Source: https://habr.com/ru/post/1337940/


All Articles