Throw and preserve stack trace not as expected as described by Code Analysis

天涯浪子 提交于 2019-12-05 03:57:24

If you are using .Net 4.5, you can use ExceptionDispatchInfo.Capture(ex).Throw(); and you will get a nice stack trace including line 22 and line 30.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            try
            {
                try
                {


                    // line 22 below
                    throw new Exception();
                }
                catch (Exception ex) // NO 'ex'
                {



                    // line 30 below
                    ExceptionDispatchInfo.Capture(ex).Throw();
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex.StackTrace);
            }

            Console.Read();
        }
    }
}

Output

   at ConsoleApplication1.Program.Main(String[] args) in c:\ConsoleApplication1\Program.cs:line 22
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at ConsoleApplication1.Program.Main(String[] args) in c:\ConsoleApplication1\Program.cs:line 30

Mark above is correct.

The stack trace is only preserved when thrown from another method.

The stack trace here will be preserved by including the original error being thrown from Method()

The following code illustrates this:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace throw_test
{
    class Program
    {
        static void Main(string[] args)
        {

            try
            {
                try
                {


                    // line 22 below
                    Method();
                }
                catch (Exception ex)
                {



                    // line 30 below
                    throw;
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex.StackTrace);
            }

            Console.Read();
        }

        public static void Method()
        {
            throw new Exception();
        }
    }
}

Output

at throw_test.Program.Method() in c:\Users\Richard\Documents\Visual Studio 2013\Projects\using_throw_closestream\using_throw_closestream\Program.cs:line 43 at throw_test.Program.Main(String[] args) in c:\Users\Richard\Documents\Visual Studio 2013\Projects\using_throw_closestream\using_throw_closestream\Program.cs:line 30

In C# 6.0 you can use exception filters to perform some logic (for example logging) without need for explicit rethrow, it will of course preserve your stack trace.

Description can be found here in Exception filters section. It says:

It is also a common and accepted form of “abuse” to use exception filters for side effects; e.g. logging. They can inspect an exception “flying by” without intercepting its course. In those cases, the filter will often be a call to a false-returning helper function which executes the side effects.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!