Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hide the current method from exception stack trace in .NET?

Tags:

c#

.net

exception

I'd like to know if there is a way to throw an exception from inside a method, but to not include that method in the exception stack trace. E.g.

void ThrowSomeException() {     throw new SomeException(); } 

And then, if I call that method from a method called Foo() I want the exception stack trace to start with at Foo(), not at ThrowSomeException(). I assume if this was possible it might be through the use of attributes on the method.

I'm interested in the general answer, but in case this isn't possible, what I'm really trying to do is create an extension method AssertEqual() for IEnumerable that I'll use in NUnit tests. So when I call myEnumerable.AssertEqual(otherEnumerable) and it fails, NUnit should report the error inside the test method, not inside the extension method.

Thanks!

like image 843
Gordon Leigh Avatar asked Jun 04 '10 10:06

Gordon Leigh


People also ask

Can exception stack trace null?

Yes. If you create a new Exception() and don't throw it, every property except Data and Message will be null.

What is stack trace in exception?

A trace of the method calls is called a stack trace. The stack trace listing provides a way to follow the call stack to the line number in the method where the exception occurs. The StackTrace property returns the frames of the call stack that originate at the location where the exception was thrown.

Should stack traces be logged?

Therefore, you should log a stacktrace if, and only if, and always if, the exception indicates a bug in the program. However, that does not always indicate that a method you write should catch and log the exception.


1 Answers

Using the code at the end of this answer allows you to write code such as:

[HideFromStackTrace] // apply this to all methods you want omitted in stack traces static void ThrowIfNull(object arg, string paramName) {     if (arg == null) throw new ArgumentNullException(paramName); }  static void Foo(object something) {     ThrowIfNull(something, nameof(something));     … }  static void Main() {     try     {         Foo(null);     }     catch (Exception e)     {         Console.WriteLine(e.GetStackTraceWithoutHiddenMethods());     }                  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ }                      // gets a stack trace string representation                        // that excludes all marked methods 

Here's one possible implementation:

using System; using System.Diagnostics; using System.Linq; using System.Reflection;  [AttributeUsage(AttributeTargets.Method, Inherited=false)] public class HideFromStackTraceAttribute : Attribute { }  public static class MethodBaseExtensions {     public static bool ShouldHideFromStackTrace(this MethodBase method)     {         return method.IsDefined(typeof(HideFromStackTraceAttribute), true);     } }  public static class ExceptionExtensions {     public static string GetStackTraceWithoutHiddenMethods(this Exception e)     {         return string.Concat(             new StackTrace(e, true)                 .GetFrames()                 .Where(frame => !frame.GetMethod().ShouldHideFromStackTrace())                 .Select(frame => new StackTrace(frame).ToString())                 .ToArray());  // ^^^^^^^^^^^^^^^     ^     }                         // required because you want the usual stack trace }                             // formatting; StackFrame.ToString() formats differently 

Note that this only causes marked methods to be excluded from one particular representation of the stack trace, not from the stack trace itself. I know of no way to achieve the latter.

P.S.: If all you want is to hide a method in the Call Stack window during a debugging session, simply apply the [DebuggerHidden] attribute to the method.

like image 68
stakx - no longer contributing Avatar answered Sep 21 '22 01:09

stakx - no longer contributing