Как избавиться от попытки поймать?
Мне скучно с окружающим кодом с попыткой поймать вот так.
try
{
//some boring stuff
}
catch(Exception ex)
{
//something even more boring stuff
}
Мне хотелось бы что-то вроде
SurroundWithTryCatch(MyMethod)
Я знаю, что могу выполнить это поведение, создав делегата с точной подписью функции, но создав делегат для всех методов в моем приложении, это просто не вариант.
Я также могу это сделать, введя IL-код, но это дорого с точки зрения производительности, поскольку он создает сборку оболочки вокруг моей.
Любые другие действительные идеи?
Ответы
Ответ 1
Во-первых, похоже, что вы слишком часто используете try/catch - особенно если вы ловите Exception
. блоки try/catch должны быть относительно редкими; если вы не сможете "обработать" исключение, вы должны просто позволить ему перейти на следующий уровень стека.
Теперь, если вы действительно хотите все эти блоки try/catch, почему это не вариант создания делегата? С анонимными методами и лямбда-выражениями, а также с делегатами Func/Action в пространстве имен System
в основном очень мало работы. Вы пишете:
public void SurroundWithTryCatch(Action action)
{
try
{
action();
}
catch(Exception ex)
{
//something even more boring stuff
}
}
а затем ваш SurroundWithTryCatch(MyMethod)
будет работать нормально, если он не принимает параметров.
В качестве альтернативы, если вы не хотите вызывать другой метод, просто напишите:
public void MyMethod()
{
SurroundWithTryCatch(() =>
{
// Logic here
});
}
Если вам нужно вернуться из метода, вы можете сделать:
public int MyMethod()
{
return SurroundWithTryCatch(() =>
{
// Logic here
return 5;
});
}
с общей перегрузкой SurroundWithTryCatch
следующим образом:
public T SurroundWithTryCatch<T>(Func<T> func)
{
try
{
return func();
}
catch(Exception ex)
{
//something even more boring stuff
}
}
В С# 2 все будет хорошо, но вывод типа вам не поможет, и вам придется использовать анонимные методы вместо лямбда-выражений.
Вернемся к началу: старайтесь чаще использовать try/catch. (try/finally должен быть намного более частым, хотя обычно он написан как оператор using.)
Ответ 2
Аспектно-ориентированное программирование также может помочь вам, но для этого может потребоваться добавить библиотеки в ваш проект, postsharp поможет вам в Это дело.
См. Ссылку http://doc.postsharp.org/1.0/index.html#http://doc.postsharp.org/1.0/UserGuide/Laos/AspectKinds/OnExceptionAspect.html#idHelpTOCNode650988000
Ответ 3
Вместо этого вы можете попытаться использовать некоторую нулевую проверку. Я могу взять пример LINQ to SQL:
var user = db.Users.SingleOrDefault(u => u.Username == 3);
if (user == null)
throw new ArgumentNullException("User", "User cannot be null.");
// "else" continue your code...
Ответ 4
Возможно, вы обрабатываете обработку исключений как коды ошибок с помощью другого синтаксиса? Так что не пытайтесь/поймать. Пусть исключение распространяется вверх.
Ответ 5
Для меня, похоже, вы просите аспектно-ориентированное программирование. Я думаю, вам стоит взглянуть на PostSharp.
Ответ 6
Я не уверен в С#, но в Java-land вы можете определить и связать все методы, а затем скрыть его под прокси-объектом. Вы можете сбежать с написанием еще большего кода, определив что-то вроде:
ExceptionCatcher.catchAll(new Runnable() {
public void run() {
//run delegate here
MyMethod();
}
});
и catchAll() просто вызовет runnable и обернет вокруг него блок try-catch.
Однако, я думаю, что вы действительно хотите, это язык, который получил закрытие поддержки. Используя закрытие, делать то, что вы хотите, очень легко.
Ответ 7
Если вы используете Java, у вас есть RuntimeExceptions, которые являются исключениями, которые означают, что что-то пошло не так, от чего нельзя ожидать восстановления. Поищи это. Начать здесь: http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
Например, Spring бит доступа к данным генерируют различные RuntimeExceptions, когда все идет не так. Работа с ними необязательна.