如何从抛出异常的方法中通过out / ref参数获取值?

时间:2010-01-20 10:47:52

标签: c# .net exception reflection byref

此代码输出“out value”。

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();
  }
}

使用反射时,如何同时获得“out value”和异常

5 个答案:

答案 0 :(得分:1)

异常绕过MethodInfo.Invoke()中的代码,该代码将堆栈帧中的[out]值复制回对象数组。 Invoke()创建的堆栈框架上的值与第1个代码段中的值相似。但这就是相似之处的结束。

答案 1 :(得分: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;
            }
        }
}

答案 2 :(得分:0)

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

答案 3 :(得分: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);        
}

答案 4 :(得分:-1)

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

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