12

此代码输出“输出值”。

class P
{
  public static void Main()
  {
    string arg = null;
    try
    {
      Method(out arg);
    }
    catch
    {
    }
    Console.WriteLine(arg);
  }
  public static void Method(out string arg)
  {
    arg = "out value";
    throw new Exception();
  }
}

但这个没有。

class P
{
  public static void Main()
  {
    object[] args = new object[1];
    MethodInfo mi = typeof(P).GetMethod("Method");
    try
    {
      mi.Invoke(null, args);
    }
    catch
    {
    }
    Console.WriteLine(args[0]);
  }
  public static void Method(out string arg)
  {
    arg = "out value";
    throw new Exception();
  }
}

使用反射时如何获得“输出值”和异常

4

5 回答 5

1

该异常绕过了 MethodInfo.Invoke() 中的代码,该代码将 [out] 值从堆栈帧复制回对象数组。Invoke() 创建的堆栈帧上的值的行为就像它在第一个代码段中一样。但这就是相似之处的结束。

于 2010-01-20T11:33:59.410 回答
1

唯一的方法是以一种考虑异常可能性的方式重载您的方法,然后在“以防万一”中传递一个。以下产生了我认为你正在寻找的东西。据我了解,问题在于反射不会直接操作通过引用传入的地址。在无一例外地到达方法终点之前,地址不会受到影响。可能是 MS 的内存保护或内存安全方案。

class P
    {
        public static void Main()
        {
            object[] args = { "1", new Exception()};
            MethodInfo mi = typeof(P).GetMethod("Method");
            try
            {
                mi.Invoke(null, args);
            }
            catch
            {
            }
            Console.WriteLine(args[0].ToString());
            Console.WriteLine(args[1].ToString());
        }
        public static void Method(ref string arg, ref Exception ex)
        {
            try
            {
                arg = "out value";
                throw new Exception();
            }
            catch (Exception exc)
            {
                ex = exc;
            }
        }
}
于 2010-01-20T11:55:40.843 回答
0

如果问题是,您如何捕捉到发生了异常并且您正在使用 Windows 窗体应用程序,您是否尝试过查看线程异常事件并将其与 SetUnhandledExceptionMode() 结合使用?

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)        
{            
    HandleException(e.Exception);        
}
于 2010-01-20T14:20:56.047 回答
0

我建议更改方法以返回 Result 对象而不是 out 参数。结果对象可以包含异常以及 arg 的值。

于 2010-01-20T11:57:19.217 回答
-1

如果方法抛出异常,则 out 参数未定义。您可以通过在第一个示例中不将其初始化为 null 来看到这一点,然后代码将无法编译。

因此,如果 Invoke 方法抛出异常,则不返回未定义的值是有意义的。

于 2010-01-20T11:06:23.403 回答