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

Maybe you could derive your own exception type and override the StackTrace property getter to exclude your method:

using System;
using System.Collections.Generic;

class MyException : Exception {

    string _excludeFromStackTrace;

    public MyException(string excludeFromStackTrace) {
        _excludeFromStackTrace = excludeFromStackTrace;
    }

    public override string StackTrace {
        get {
            List<string> stackTrace = new List<string>();
            stackTrace.AddRange(base.StackTrace.Split(new string[] {Environment.NewLine},StringSplitOptions.None));
            stackTrace.RemoveAll(x => x.Contains(_excludeFromStackTrace));
            return string.Join(Environment.NewLine, stackTrace.ToArray());
        }
    }
}

class Program {

    static void TestExc() {
        throw new MyException("Program.TestExc");
    }

    static void foo() {
        TestExc();
    }

    static void Main(params string[] args) {
        try{
            foo();
        } catch (Exception exc){
            Console.WriteLine(exc.StackTrace);
        }
    }

}

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.


I am guessing that you want to do this in order to consolidate code that is used to create the exception?
In that case, rather than write a ThrowException() function, why not write a GetException() function? Then in Foo, just do throw GetException();

Tags:

C#

.Net

Exception