Как получить значение через параметр out / ref из метода, который выдает исключение? - PullRequest
12 голосов
/ 20 января 2010

этот код выводит "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 ]

1 голос
/ 20 января 2010

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

1 голос
/ 20 января 2010

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

Если проблема в том, как вы узнаете, что произошло исключение, и вы работаете с приложением 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);        
}
0 голосов
/ 20 января 2010

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

0 голосов
/ 20 января 2010

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

Итак, для метода Invoke имеет смысл не возвращать неопределенное значение, если метод выдает исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...