Есть ли лучший способ игнорировать исключение в С#, чем помещать его в блок catch try и ничего не делать в catch? Я считаю, что этот синтаксис является громоздким. Для кодового блока я не могу просто "пометить" его таким образом, чтобы среда выполнения знала, какие исключения игнорируются?
Игнорировать исключение в С#
Ответ 1
Я не думаю, что есть трюк, чтобы избежать исключения, но вы можете использовать следующий фрагмент кода:
public void IgnoreExceptions(Action act)
{
try
{
act.Invoke();
}
catch { }
}
Использование метода выглядит так:
IgnoreExceptions(() => foo());
Другое решение - использовать AOP (Aspect Oriented Programming) - там есть инструмент PostSharp, который позволяет вам создать атрибут, который будет ловить все исключения в конкретной сборке/классе/методе, которые ближе к тому, что вы ищете.
Ответ 2
Вы можете сделать это с помощью АОП. Например, Postsharp позволит вам легко реализовать такой атрибут, который будет пропускать определенные исключения в методах, к которым вы применили такой атрибут. Без АОП я не вижу никакого хорошего способа сделать это (если мы предположим, что есть хороший способ сделать такие вещи;)).
С помощью Postsharp вы сможете украсить свои методы таким образом:
[IgnoreExceptions(typeof(NullReferenceException), typeof(StackOverflowException))]
void MyMethod() { ... }
Ответ 3
Один из способов - воспользоваться преимуществами Aspect Oriented Programming (AOP). Посмотрите PostSharp. Здесь приведен пример использования атрибута исключения для метода, так что если произойдет исключение, вы можете справиться с ним с помощью блока try..catch.
EDIT:
А да, предложение Дрора тоже хорошее. Я видел примеры этого в корпоративной библиотеке. Это было бы лучше, если бы вы не хотели иметь стороннюю структуру в своем проекте (т.е. PostSharp).
Ответ 4
Я не знаю никакого механизма, который позволил бы вам это сделать.
В целом, также считается очень плохой практикой игнорировать исключения. Исключения (или всегда должны быть) подняты по уважительной причине; если ничего другого, вы должны, по крайней мере, зарегистрировать их.
Если вы знаете, что определенный тип исключения не имеет решающего значения для вашего приложения, вы можете предотвратить его сбой с помощью события Application.UnhandledException, проверяя это исключение. Обратите внимание, что это все равно будет распространять исключение через все кадры стека до самого низа.
Ответ 5
Нет. Когда происходят исключения, они перемещают резервную копию стека вызовов до тех пор, пока они не будут обработаны блоком catch
или весь процесс не завершится.
Ответ 6
Нет. Если выбрано исключение, обычно это критическая ошибка, которая произошла. Вы не хотите игнорировать его.
Вместо этого вы должны переписать свой код, чтобы проверить наличие ошибок, и только если он действительно терпит неудачу, выполняется исключение.
Например, используя Int32.TryParse вместо Int32.Parse, чтобы проверить, является ли объект действительным целым числом. Помните, что исключения очень дороги, когда их отливают, и многие приведения сильно влияют на производительность вашего приложения.
Ответ 7
Пустые блоки блокировки - очень вонючий запах кода. Короче говоря, вы не должны придерживаться сокращенного способа их написания.
Правило № 1: "Не поймите, если вы не можете с этим справиться". Правило № 1а есть: "Если вы действительно не обрабатывали исключение, повторите его бросок".
Если вы просто пытаетесь предотвратить сбой приложения, в большинстве случаев есть более подходящие механизмы..NET включает события UnhandledException на уровнях Application, Dispatcher и AppDomain, а также события, посвященные уведомлению вас о необработанных исключениях из фоновых потоков. На этом уровне, если вы не можете проверить состояние своего приложения, лучшим вариантом может быть уведомление пользователя о том, что произошло что-то плохое и прекратить действие приложения.
Ответ 8
Я хотел внести вклад в методы расширения, созданные мной на основе предыдущих ответов. Надеюсь, это поможет кому-то.
/// <summary>
/// Extension methods for <see cref="Action"/> objects.
/// </summary>
public static class ActionExtensions
{
/// <summary>
/// Executes the <paramref name="action"/> and ignores any exceptions.
/// </summary>
/// <remarks>
/// This should be used in very rare cases.
/// </remarks>
/// <param name="action">The action to execute.</param>
public static void IgnoreExceptions(this Action action)
{
try { action(); }
catch { }
}
/// <summary>
/// Extends an existing <see cref="Action"/> so that it will ignore exceptions when executed.
/// </summary>
/// <param name="action">The action to extend.</param>
/// <returns>A new Action that will ignore exceptions when executed.</returns>
public static Action AddIgnoreExceptions(this Action action)
{
return () => action.IgnoreExceptions();
}
}
И модульные тесты:
[TestClass]
public class ActionExtensionsTests
{
[TestMethod]
public void IgnoreException()
{
Action justThrow = () => { throw new InvalidOperationException(); };
justThrow.IgnoreExceptions();
}
[TestMethod]
public void AddIgnoreException()
{
Action justThrow = () => { throw new InvalidOperationException(); };
var newAction = justThrow.AddIgnoreExceptions();
newAction();
}
}
Ответ 9
public static void Ignore<T>(Action a) where T : Exception
{
try
{
a();
}
catch (T)
{
}
}
Для использования:
Ignore<InvalidOperationException>(() => foo());