-1

Going along the same ideas found in this question. I need to be able to recreate an exception inside a function that doesnt know ahead of time what kinds of exceptions will be passed in.

My code so far:

//Code where original exception in created
ArgumentException ex = new ArgumentException(SixteenthsFractional, "Not a recognized architectural string");
RecievingCode(ex, ex.GetType());
throw ex;


public static void RecievingCode(Exception passedException, Type passedExceptionType)
{
    var exception = Activator.CreateInstance(passedExceptionType);
    //Can I cast the passedException to this type?
}

How can I recreate the specific exception just like the person did with the Child1 object in the answer in this question?

(This is not a system architecture question. I have my reasons for why I need to do it this way)

Community
  • 1
  • 1
Jeremy Lin
  • 400
  • 3
  • 13
  • 1
    Why can't you use generics and type inference? – Kendall Frey Feb 28 '14 at 14:57
  • Could you give an example of what that would look like – Jeremy Lin Feb 28 '14 at 15:00
  • 2
    Your code snippet is just confusing, why would you want to rebuild the exception if you are already passing the exception instance? For this to be answerable you really need to provide some context. – James Feb 28 '14 at 15:05
  • See my answer. It's not clear what you need. If you want to access the specific type of exception at runtime, you can't do it at compile time. – Kendall Frey Feb 28 '14 at 15:07
  • "Can I cast the passedException to this type?" Casts are resolved at compile time, so as your code is, you can't. – Kendall Frey Feb 28 '14 at 15:13
  • 1
    @Khnle-KevinLe Yes, yes I am. I do some coding to keep my mind sharp. Since I graduated from Harvard, the NBA isn't mentally challenging enough to keep me satisfied. – Jeremy Lin Feb 28 '14 at 15:16
  • 1
    Casting makes only sense if you want to access members of the resulting type, but you can only do so, if you know the type at design time (compile time). So dynamically casting at runtime seems to have no benefit. – Olivier Jacot-Descombes Feb 28 '14 at 15:16

3 Answers3

3

An object has a type, and that object will always have that type regardless of what you cast it to. So even though your parameter is

Exception passedException

It still is an ArgumentException. The method just accepts "any Exception type". You can safely cast an Exception back to the actual type of the object, but to do so you'll need to know what type it was in the first place:

ArgumentException argEx = passedException as ArgumentException;
if (argEx != null)
{
    ...
}

or

if (passedException is ArgumentException)
{
    ArgumentException argEx = (ArgumentException)passedException;        
}

You can't switch on types though, so this will result in a whole bunch of if/else statements if you have a bunch of different functionality for each exception type.

C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
  • Is there no way to incorporate the passed type (second parameter in RecievingCode) so that I do know what I want to cast to? – Jeremy Lin Feb 28 '14 at 15:13
  • @JeremyLin You can't 'cast' to a type. That's not how casting works. If you pass an `ArgumentException`, that's what you get at runtime, but the compiler can only know that it's an `Exception`. – Kendall Frey Feb 28 '14 at 15:15
  • 1
    @JeremyLin the `passedException` is already of that type. The second parameter is useless because `passedException.GetType()` returns the same type. – C.Evenhuis Feb 28 '14 at 15:15
  • 1
    @JeremyLin I think it's time you show us what you want to do with the "cast" Exception, perhaps we're better able to help you then. – C.Evenhuis Feb 28 '14 at 15:16
  • @C.Evenhuis I didnt realize GetType would return ArgumentException. Thats helpful. So the only difference between throwing the exception in the recieving code and the original context is the stack trace? If so, can the stacktrace be passed as a parameter and how? – Jeremy Lin Feb 28 '14 at 15:21
  • 1
    @JeremyLin In your exception handler, you should not `throw ex` but just `throw`, to maintain the stack trace. The exception you pass to your function is exactly that what you caught. – C.Evenhuis Feb 28 '14 at 15:25
1

If you use generic type inference, you can do this:

public static void RecievingCode<TException>(TException passedException) where TException : Exception
{
    // stuff
}

You would call it like this:

RecievingCode(ex);
Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • In what way does this let the OP *"fully recreate"* an exception? – James Feb 28 '14 at 15:05
  • What does *"fully recreate"* mean anyway? Re-throw the same instance of the exception? Pass it in? – NWard Feb 28 '14 at 15:07
  • @James If you know what the OP is trying to do, please do post an answer. I'm dying to know. – Kendall Frey Feb 28 '14 at 15:08
  • @KendallFrey I have no idea which is why I have added a comment for the OP to clarify. As it stands, the question doesn't make any sense. – James Feb 28 '14 at 15:15
0

Although only types derived from Exception can be thrown or caught, the are very few rules about what such types can do or contain, and such rules are not sufficient to guarantee the existence of any general-purpose means via which instances of any and all such types can be recreated. Certainly types can be designed to be "difficult", and while most types would have little reason for doing so, there's no guarantee that the creator of a type wouldn't find some benefit to a design which happens to be incompatible with any straightforward copying approach.

For example, consider the following sketch of an exception derivative:

void SillyException : Exception
{
    SillyException shouldBeThis;
    public SillyException()
    {
      shouldBeThis = this;
    }
    public override String ToString()
    {
      if (shouldBeThis != this) doSometingBad();
      return base.ToString();
    }
}

Code which knows about field shouldBeThis might be able to use Reflection to set it, but there would be no way for code which had no reason to suspect the existence of a variable to properly set it to this. While that particular example is of course highly contrived, there are a variety of similar reasons why copying an exception may be essentially impossible. For example, a class might keep a ThreadStatic variable which holds the exception--if any--thrown by the last attempted operation on the class on that thread, and so that if cleanup fails it can build a composite exception which combines the original exception with cleanup exception(s). If multiple exceptions include references to each other, an attempt to copy the exception which isn't aware of the different exceptions and their relationships could easily result in a broken object graph, which could cause an attempt to examine and report what happened to crash with a stack overflow.

If you know enough about the exceptions that will be thrown to know that such designs are not an issue, then an approach using generics and Reflection might be usable, but the suitability of such designs will depend upon exactly what you know and exactly what you're trying to do.

supercat
  • 77,689
  • 9
  • 166
  • 211