Проблема со слишком многими попытками поймать - PullRequest
0 голосов
/ 20 декабря 2010

Можно ли написать метод наподобие outType? TryDo(func, out exception, params), который вызывает func(arg1,arg2,arg3,...), в параметрах которого содержится arg1,arg2,arg3,..., а затем он возвращает возвращаемое значение func, а в случае возникновения какого-либо исключения возвращает ноль и устанавливает исключение?

Можно ли сделать это лучше с помощью другой сигнатуры функции?

, например, у меня есть string Foo1(int i) { return i.ToString()}

void Foo2(int[] a) {throw new Exception();}

, а затем вызовите

string t = TryDo(Foo1, out ex, {i});

TryDo(Foo2, out ex, {});

----------- Отредактировано ------------------

        string t;
        SomeClass c;
        try
        {
            t = Foo1(4, 2, new OtherClass());
        }
        catch (Exception ex)
        {
            Log(ex);
            if (/*ex has some features*/)
                throw ex;
        }

        try
        {
            Foo2();
        }
        catch (Exception ex)
        {
            Log(ex);
            if (/*ex has some features*/)
                throw ex;
        }
        .
        .
        .

Я хочу сделать это так.

        string t = TryDo(Foo1, out ex, {4, 2, new OtherClass());
        Examine(ex);
        SomeClass c = TryDo(Foo2, out ex, {});
        Examine(ex);

Ответы [ 5 ]

3 голосов
/ 20 декабря 2010

То, что вы спрашиваете, указывает на то, что вы неправильно поняли, как должны обрабатываться исключения. Повсеместное использование try / catch может привести к нежелательным результатам и усложнить отладку приложения.

Короче, обрабатывать исключения можно только в следующих случаях:

  1. Вы можете обработать исключение и вернуть обещанный результат
  2. Поймать определенные исключения слоя и заменить их более общими исключениями (SqlException -> DataSourceException)
  3. Поймать все в порядке в верхнем слое
  4. Поймать все в порядке в потоках (поскольку неперехваченные исключения в потоках приведут к краху вашего приложения)

Больше информации в моем блоге: http://blog.gauffin.org/2010/11/do-not-catch-that-exception/

Обновление

ПОЖАЛУЙСТА не используйте throw ex. Вы уничтожаете исходный стек вызовов и, следовательно, скрываете исходное исключение. throw; твой щенок. Используйте его везде и всегда.

2 голосов
/ 20 декабря 2010

Я бы не использовал параметры out, за исключением случаев, когда это абсолютно необходимо.

Вот цитата из Руководства по проектированию для разработки библиотек фреймворков :

Избегайте использования выходных или опорных параметров.

Работа с элементами, которые определяют параметры вывода или ссылки, требует, чтобы разработчик понимал указатели, тонкие различия между типами значений и ссылочными типами, а также различия при инициализации между параметрами вывода и ссылки.

Вместо этого вы можете создать тип возврата, который обернет результат вашего вызова:

class CallResult<T> where T : class {
  public CallResult(T result) { Result = result; }
  public CallResult(Exception exception) { Exception = exception; }
  public T Result { get; private set; }
  public Exception Exception { get; private set; }
  public Boolean IsSuccessful { get { return Exception == null; } }
}

Ваш метод может быть реализован так:

CallResult<T> TryDo<T>(Func<Object[], T> action, params Object[] args) where T : class {
  try {
    return new CallResult<T>(action(args));
  }
  catch (Exception ex) {
    return new CallResult<T>(ex);
  }
}

Вы можете назвать это так:

var callResult = TryDo<String>(Foo1, 4, 2, new OtherClass());
if (!callResult.IsSuccessful)
  Examine(callResult.Exception);

Однако, если вы намереваетесь сбросить исключение в методе Examine, потеряв трассировку стека , вам действительно следует пересмотреть свой подход .

2 голосов
/ 20 декабря 2010

Да, это возможно.

Но почему вы хотите вернуть возможное исключение таким образом?Вы можете бросить дальше и обработать в нужном месте.

0 голосов
/ 20 декабря 2010

если у вас слишком много попыток ... поймать (я не могу понять почему), вы можете пойти на AOP для централизации обработки исключений.

Ниже вы можете найти ссылку, объясняющую, как использоватьэто:

http://www.codeproject.com/KB/architecture/ExceptionHandlingWithAOP.aspx

0 голосов
/ 20 декабря 2010

Да, но зачем вам это?

int? TryDo(delegate d, out Exception e, params object[] par)  
{
   try
   {
      int res = d.Invoke(par);
      e = null;
      return res;
   }  
   catch(Exception ex) { e = ex; return null; }
}
...