【问题标题】:C# : Better way to code this?C#:更好的编码方式?
【发布时间】:2011-03-01 20:00:13
【问题描述】:

我有一个代码块来处理我的应用程序中的异常,它使用 if/else 块来获取消息内容。
我的代码如下:

// define variable to hold exceptions...
var exceptionMessage = new StringBuilder();  
// based on the exception type...  
if (expType == typeof(EntityValidationException))  
{  
    // append the relevant message to the text...  
    exceptionMessage.Append(exception.InnerException.Message);  
}  
else if (expType == typeof(ValidationException))  
{  
    // This is the type of error generated when entities are validated  
    var validationException = (ValidationException)exception;  
    exceptionMessage.Append(validationException.InnerException.Message);  
}  
else if (expType == typeof(DomainSecurityException))  
{  
    // These are security breaches  
    var domainSecurityException = (DomainSecurityException)exception;  
    exceptionMessage.Append(domainSecurityException.InnerException.Message);  
}  
else if (expType == typeof(DomainInternalMessageException))  
{  
    // These are the type of errors generated a System.Exception occurs and is  
    // converted by the exception handling policy to a more friendly format  
    var domainInternalMessageException = (DomainInternalMessageException)exception;  
    exceptionMessage.Append(domainInternalMessageException.ExceptionMessage);  
}
else  
{  
    exceptionMessage.AppendFormat(ErrorMessagesRes.Standard_Error_Format, "Unknown error", exception.InnerException.Message);   
}  
// this shows the message as an alert popup...  
this.DisplayJavascriptMessage(exceptionMessage.ToString());

这已经从原始版本进行了改进,但只是想看看是否有针对此代码的更简洁、更可重用的解决方案。
提前感谢
马丁

【问题讨论】:

  • 你为什么不switch()你的expType?这会给你的代码带来更多的结构。
  • 我试过了,但你不能使用非整数类型的 switch,这就是我没有使用那个结构的原因。
  • @Martin:你不能在Types 上switch
  • @m.edmondson - 什么不正确?你不能打开非整数类型?
  • @Martin S - 抱歉我看错了,以为你输入了整数类型 :-)

标签: c# if-statement


【解决方案1】:

假设这是一个传递异常对象的例程(并且不直接参与 try catch 块)并假设“异常”对象最终派生自 Exception,您可以稍微精简一下代码

// define variable to hold exceptions...
            var exceptionMessage = new StringBuilder();

            // based on the exception type...  
            if (exception is EntityValidationException || exception is ValidationException || exception is DomainSecurityException)
            {
                // append the relevant message to the text...  
                exceptionMessage.Append(exception.InnerException.Message);
            }

            else if (expType == typeof(DomainInternalMessageException))
            {
                // These are the type of errors generated a System.Exception occurs and is  
                // converted by the exception handling policy to a more friendly format  
                var domainInternalMessageException = (DomainInternalMessageException)exception;
                exceptionMessage.Append(domainInternalMessageException.ExceptionMessage);
            }
            else
            {
                exceptionMessage.AppendFormat(ErrorMessagesRes.Standard_Error_Format, "Unknown error", exception.InnerException.Message);
            }
            // this shows the message as an alert popup...  
            this.DisplayJavascriptMessage(exceptionMessage.ToString());

【讨论】:

    【解决方案2】:
        var exceptionMessage = new StringBuilder();  
    
        try
        {
        }
        catch(EntityValidationException exc)
        {  
            exceptionMessage.Append(exc.InnerException.Message);  
        }  
        catch(ValidationException exc)  
        {  
            exceptionMessage.Append(exc.InnerException.Message);  
        }  
        ....
    

    确保 catch 块按照从最不通用到最通用的正确顺序排列。

    【讨论】:

    • 它是针对 Web 应用程序的,我们希望处理错误,将异常消息传递到日志文件,并显示一个简单的错误页面,而不是应用程序因错误堆栈而崩溃。它可以工作,但是在查看代码时,我想知道它是否可以改进。
    • @thecoop - 有问题的代码没有显示抛出的内容
    • 原始异常源应该用这个 try 块包装。
    • @Jukub Konecki - 谢谢,但正在传入异常,因此 try/catch 块不起作用。我正在使用异常记录并将其转换为更友好的消息。
    • @Jukub Konecki - 对不起。目前,每个 aspx 页面事件都使用一个 try/catch 块,任何异常都会传递给这个过程。然后尝试找出类型并获取消息详细信息。我不想改变它的处理方式,因为我们现在离开发太远了,但我只是想让代码在未来更具可读性和可重用性。感谢您迄今为止提出的所有建议。
    【解决方案3】:
    public static Exception On<T>(this Exception e, Action<T> action)
    {
        if(e is T)
            action((T)e);
    
        return e;
    }
    
    exception.
        On<ValidationException>(e => exceptionMessage.Append(e.InnerException.Message)).
        On<DomainInternalMessageException>(e => ...);
    

    【讨论】:

    • @Martin S:让On 方法成为某个静态类的成员,并使用这个庞大的方法调用链重写您的异常处理代码。
    • 好的,但是我在尝试使用 on 方法将“System.Exception”类型的表达式转换为“T”时遇到错误。
    • 我尝试实现@Anton 的代码,但是在方法中得到了转换错误;我不确定如何处理我想做的更多事情,而不仅仅是附加到 On 方法中的 stringbuilder 对象,我也可以简单地将 On 传递到链中以处理 else 吗?
    【解决方案4】:

    每当我看到那些if else if 声明时,我认为这必须更容易完成。在某些情况下 switch 语句会有所帮助,但正如 this question 已经说过的那样,无法打开 Type。

    所以我常用的另一种解决方法是某种Dictionary&lt;Type, something&gt;something 的位置取决于我想做什么。最适合您的案例的匹配结构可能类似于Dictionary&lt;Type, Func&lt;Exception, string&gt;&gt;,可以在您的案例中使用,如下所示:

    Dictionary<Type, Func<Exception, string>> _FunctorsForType;
    
    private void InitializeFunctorsForType()
    {
        _FunctorsForType = new Dictionary<Type, Func<Exception, string>>();
    
        // Add a normal function
        _FunctorsForType.Add(typeof(ArgumentException), (Func<Exception, string>)ForArgumentException);
    
        // Add as lambda
        _FunctorsForType.Add(typeof(InvalidCastException), (ex) =>
            {
                // ToDo: Whatever you like
                return ex.Message;
            });
    }
    
    private string ForArgumentException(Exception ex)
    {
        var argumentException = ex as ArgumentException;
    
        if (argumentException == null)
        {
            throw new ArgumentException("Exception must be of type " + typeof(ArgumentException).Name);
        }
    
        // ToDo: Whatever you like
        return ex.Message;
    }
    
    private void Usage(Type type)
    {
        Func<Exception, string> func;
    
        if (!_FunctorsForType.TryGetValue(type, out func))
        {
            throw new ArgumentOutOfRangeException("Exception type " + type.Name + " is not supported.");
        }
    
        var message = func(new NullReferenceException());
    
        // ToDo: Whatever you have to do with your message
    }
    

    因此,通过这种结构,您不必将所有的智慧都投入到一个大的 if-else 语句中。相反,您可以将它们放在单独的函数中(可能在不同的类中),以便更好地组织如何处理您希望支持的每种类型。

    【讨论】:

      【解决方案5】:
      string exceptionMessage;
      if (expType == typeof(EntityValidationException) || 
          expType == typeof(ValidationException) ||
          expType == typeof(DomainSecurityException))
        exceptionMessage = exception.InnerException.Message;
      else if (expType == typeof(DomainInternalMessageException))  
       exceptionMessage = ((DomainInternalMessageException)exception).ExceptionMessage;
      else  
       exceptionMessage = string.Format(ErrorMessagesRes.Standard_Error_Format, "Unknown error", exception.InnerException.Message);  
      
      this.DisplayJavascriptMessage(exceptionMessage);
      

      有点压缩,没有 cmets。

      【讨论】:

      • 谢谢,我正在做的更简单的版本。我先看看安东的回复。
      • 谢谢大家 - 我会离开并查看选项。感谢您的时间和帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-24
      • 2013-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多