Подтвердить что ты не робот

Как получить значение через параметр out/ref из метода, который генерирует исключение?

этот код выводит значение "out".

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

как я могу получить как "исходящее значение", так и исключение, когда использует отражение?

4b9b3361

Ответ 1

Исключение обходит код в MethodInfo.Invoke(), который копирует значение [out] из кадра стека обратно в массив объектов. Значение в стеке стека, созданное Invoke(), ведет себя точно так же, как в первом фрагменте. Но то, где сходство заканчивается.

Ответ 2

Единственный способ - перегрузить ваш метод таким образом, который учитывает возможность исключения, а затем передать его в "на всякий случай". Следующее производит то, что я думаю, что вы ищете. Проблема, насколько я понимаю, заключается в том, что отражение не приводит к непосредственному манипулированию адресами, передаваемыми посредством ссылки. Адреса не затрагиваются до тех пор, пока конечная точка метода не будет достигнута без исключения. Возможно, защита памяти или схема защиты памяти от 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;
            }
        }
}

Ответ 3

Я бы предложил изменить метод, чтобы вернуть объект Result вместо параметра out. Объект результата может содержать исключение, а также значение вашего аргумента.

Ответ 4

Если проблема в том, как вы поймали, что произошло исключение, и вы работаете с приложением Windows Forms, попробовали ли вы посмотреть Событие исключения потоков и объединить его с 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);        
}

Ответ 5

Параметр out undefined, если метод генерирует исключение. Вы можете увидеть это, не инициализируя его нулем в первом примере, тогда код не будет компилироваться.

Таким образом, метод Invoke имеет смысл не возвращать значение undefined, если метод генерирует исключение.