【问题标题】:Ignore Exception in C#忽略 C# 中的异常
【发布时间】:2011-02-06 12:06:59
【问题描述】:

有没有更好的方法来忽略 C# 中的异常,而不是将其放在 try catch 块中并且在 catch 中什么也不做?我发现这种语法很麻烦。对于代码块,我不能简单地“标记”它,以便运行时知道要忽略哪些异常吗?

【问题讨论】:

  • 我知道忽略异常是一种不好的编程习惯,但我的问题不是这样。我看不出有一个空的 catch 块有什么意义,因此是这个问题。

标签: c# exception


【解决方案1】:

我不认为有什么技巧可以避免异常但是你可以使用下面的代码sn-p:

public void IgnoreExceptions(Action act)
{
   try
   {
      act.Invoke();
   }
   catch { }
}

使用方法如下:

IgnoreExceptions(() => foo());

另一种解决方案是使用 AOP(面向方面​​的编程) - 有一个名为 PostSharp 的工具,它使您能够创建一个属性来捕获特定程序集/类/方法中的所有异常,这更接近您的实际情况正在寻找。

【讨论】:

  • @Dror,好主意。但是请注意,您的代码包含一个微妙的错误:CLR 实际上允许抛出 any 值,而不仅仅是 Exception 类型的对象(此限制仅由 C# 强制执行)。所以,你应该重写你的catch 块:catch { };否则,某些不寻常的异常实际上可能会返回给调用者! -- 参见例如this blog article(大约往下两页)供参考。
  • (我现在已经修复了。我趁机发现你的代码中有另一个错字,我也更正了。希望你不介意。)
  • 为什么不使用act.Invoke()而不是act()?
  • 通常当出现异常时程序会中断。所以如果我使用 try 和 catch 那么程序将运行 catch 而不是 break?
  • 查看我的回答下面的通用选项,您可以在其中指定要忽略的异常。
【解决方案2】:

你可以用 AOP 做到这一点。例如,Postsharp 将允许您轻松实现此类属性,该属性将跳过您应用此类属性的方法中的特定异常。如果没有 AOP,我看不到任何好的方法来做到这一点(如果我们假设有一种好的方法来做这些事情;))。

使用 Postsharp,您将能够以这种方式装饰您的方法:

[IgnoreExceptions(typeof(NullReferenceException), typeof(StackOverflowException))]
void MyMethod() { ... }

【讨论】:

    【解决方案3】:

    一种方法是利用面向方面的编程 (AOP)。看看PostSharpHere 是在方法上使用异常属性的示例,这样如果发生异常,您可以使用 try..catch 块来处理它。

    编辑:

    啊,是的,Dror 的建议也不错。我在 Enterprise Library 中看到过这样的例子。如果您不想在项目中使用第三方框架(即 PostSharp),那就更好了。

    【讨论】:

      【解决方案4】:

      我不知道有什么机制可以让你这样做。

      通常,忽略异常也被认为是一种非常糟糕的做法。出于充分的理由(或应该始终)提出例外;如果不出意外,您至少应该记录它们。

      如果您知道某种类型的异常对您的应用程序并不重要,您可以使用Application.UnhandledException 事件来防止它崩溃,检查这种异常。请注意,这仍会将异常通过所有堆栈帧传播到最底部。

      【讨论】:

        【解决方案5】:

        我想贡献我根据之前的答案创建的扩展方法。希望它可以帮助某人。

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

        【讨论】:

          【解决方案6】:
              public static void Ignore<T>(Action a) where T : Exception
              {
                  try
                  {
                      a();
                  }
                  catch (T)
                  {
                  }
              }
          

          使用方法:

              Ignore<InvalidOperationException>(() => foo());
          

          【讨论】:

            【解决方案7】:

            没有。当出现异常时,它们会返回调用堆栈,直到它们被 catch 块处理或整个进程终止。

            【讨论】:

              【解决方案8】:

              没有。如果抛出异常,通常是已经发生的严重错误。你不想忽略它。

              相反,您应该重写代码以检查错误,并且只有当它确实失败时,才会抛出异常。

              例如,使用 Int32.TryParse 而不是 Int32.Parse 来检查对象是否为有效整数。请记住,异常在强制转换时非常昂贵,而且许多强制转换会严重影响应用程序的性能。

              【讨论】:

              【解决方案9】:

              空的 catch 块是一种非常臭的代码气味。简而言之,您不应该追求一种速记方式来编写它们。

              第 1 条规则是,“如果你不能处理,就不要抓住它。” 规则 #1a 是,“如果您实际上没有处理异常,请重新抛出它。”

              如果您只是想防止应用崩溃,则可以在大多数情况下使用更合适的机制。 .NET 包括 Application、Dispatcher 和 AppDomain 级别的 UnhandledException 事件,以及专门用于通知您后台线程上未处理的异常的事件。在此级别,如果您无法验证应用的状态,最好的选择可能是通知用户发生了一些不好的事情并终止应用。

              【讨论】:

              • 吃异常就是处理异常。例如,您不希望您的日志框架抛出阻止您的业务功能正常工作的异常。基本上,您不希望您的主要任务仅仅因为可选的非必要代码中可能存在问题而失败。规则 #1 真的应该是不制定任何规则,因为这一切都取决于。你总是需要了解你为什么做某事,以及它有什么影响。另外,您的回复以何种方式使原始问题变得清晰?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-03-13
              • 2022-06-16
              • 1970-01-01
              相关资源
              最近更新 更多