C# 在挡块内运行时检测

C# 在挡块内运行时检测,c#,catch-block,C#,Catch Block,如何检测当前正在执行的代码何时从catch块中被调用 void SomeFunction() { // how do I detect whether I am being called from within a catch block? } 编辑: 对于那些提出问题的人,我想实现这样一个类,更不用说错误冒泡逻辑了:在编写这个代码示例时,我得到了一个编译器错误“catch子句之外不允许有无参数的throw语句”,所以这有点破坏了我的想法 public class ErrorManag

如何检测当前正在执行的代码何时从catch块中被调用

void SomeFunction()
{
    // how do I detect whether I am being called from within a catch block?
}
编辑:

对于那些提出问题的人,我想实现这样一个类,更不用说错误冒泡逻辑了:在编写这个代码示例时,我得到了一个编译器错误“catch子句之外不允许有无参数的throw语句”,所以这有点破坏了我的想法

public class ErrorManager {

    public void OnException(Exception ex) {
        LogException(ex);
        if (IsInsideCatchBlockAlready()) {
            // don't destroy the stack trace, 
            // but do make sure the error gets bubbled up
            // through the hierarchy of components
            throw; 
        } else {
            // throw the error to make it bubble up 
            // through the hierarchy of components
            throw ex; 
        }
    }

    void LogException(Exception ex) {
        // Log the exception
    }

    bool IsInsideCatchBlockAlready() {
        // How do I implement this?
    }
}

你没有。没有办法知道,如果抛出异常,它是否会被捕获或使程序崩溃。您可以在编译时使用代码分析工具进行猜测,但在代码运行时,这不是一个选项。

不,没有办法做到这一点

通过分析生成的(IL)代码可能会有一些偷偷摸摸的方法,但我很确定您不希望这样

这是标准控制台应用程序捕获异常的IL:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       34 (0x22)
  .maxstack  1
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  ldstr      "OK"
    IL_0007:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000c:  nop
    IL_000d:  nop
    IL_000e:  leave.s    IL_0020
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0010:  pop
    IL_0011:  nop
    IL_0012:  ldstr      "Err"
    IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_001c:  nop
    IL_001d:  nop
    IL_001e:  leave.s    IL_0020
  }  // end handler
  IL_0020:  nop
  IL_0021:  ret
} // end of method Program::Main
如果您可以分析当前代码(假设它位于
“OK”
)是否在该块中,您可以提取
尝试。。。捕捉
块。当然,这并不考虑调用其他方法


这听起来也是解决你问题的一个荒谬的办法,所以在你投入你不想要的事情之前,想想你是否真的想这样做。

你问错了问题,我的朋友

大多数框架允许通过特定方法处理未捕获的异常。WPF、C#webforms、asp,所有这些都有一个“未处理的异常处理”例程,您可以在应用程序级别连接到该例程

例如,普通C#表单应用程序使用:

    Application.ThreadException += new ThreadExceptionEventHandler(MyCommonExceptionHandlingMethod)

private static void MyCommonExceptionHandlingMethod(object sender, ThreadExceptionEventArgs t)
{
    //Exception handling...
}
因此,您只需要声明exceptionmanager类,然后将该类连接到异常处理中,例如:

    Application.ThreadException += new ThreadExceptionEventHandler(TellMyClass)

private static void TellMyClass(object sender, ThreadExceptionEventArgs t)
{
     ExceptionManager.HandleException(sender, t);
}
但是,我使用的模式是:

public static class UnhandledExceptionManager {
    Logger _logger;
    public static void RegisterToHandleFormsException(){
        _logger = new Logger();
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        Application.ThreadException += OnThreadException;
        AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
    }

    public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e){
        HandleException((Exception)e.ExceptionObject);
    }
    private static void HandleException(Exception exception, [CallerMemberName] string methodName = "")
        {
            try
            {
                _logger.Error(methodName, exception);
            }
            catch (Exception e)
            {
                Debug.WriteLine("({0}) {1}", methodName, e);
            }
        }
}
在Program.cs中使用的:

public static void Main(){
  UnhandledExceptionManager.RegisterToHandleFormsException();
  //etc
}

如其他答案所述,你不能。您可以通过向方法传递参数来伪造它,但这似乎是一种代码味道。

Windows上的CLR异常只是另一种SEH。阅读经典:。显然,可以检测代码在SEH处理程序中运行,因为必须检测。包含所需的所有内容,前提是您是操作系统或调试器,并且知道如何解释它


对你来说,我强烈建议你退后一步,走记录在案的道路。如果需要,请包装您的登录到try/catch块,以避免从要求不抛出的代码中泄漏异常。确保你处理得当,因为它很特别。挂接到适当的日志记录和错误报告中,并/或(视情况而定)。

您始终可以用简单的方法完成:

void SomeFunction(bool isCalledFromCatch)
{
    // how do I detect whether I am being called from within a catch block?
}

try
{
}
catch(...)
{
    SomeFunction(true);
}

你没有。如果您认为有必要,那么您就是做错了;看看接下来会发生什么:)只是开玩笑。解释一下你为什么需要这个,我们可以帮你解决这个XY问题。或者,通过引入
bool throwIfNotFound
参数或您想要实现的任何功能,让您的方法根据需要抛出异常。一个方法永远不应该依赖于调用它的人或方法,这就是参数的用途。我想hacky
bool catch=true
是不可能的。我强烈建议你告诉我们你试图实现什么,因为你几乎肯定会走上一条非常糟糕的道路。