如何避免在以下代码中转换为(ServiceException)?

时间:2011-12-20 04:42:16

标签: c#

我创建了一个这样的异常类:

public class ServiceException : ApplicationException {

    public Dictionary<string, string> Errors { get; set; }

    public ServiceException(Exception ex) : base("Service Exception", ex) {
      Errors = new Dictionary<string, string>();
    }
    public ServiceException() : this(null) {}

}

以下代码失败:

protected void log(Exception ex)
{
    if (ex is ServiceException)
    {
        var y = (ServiceException)
        ModelState.Merge(ex.Errors);
    }
    else
    {
        Trace.Write(ex);
        ModelState.AddModelError("", "Database access error: " + ex.Message);
    }
}

它在编译时生成以下错误:

  

错误5'System.Exception'不包含'错误'的定义   没有扩展方法'错误'接受第一个类型的参数   可以找到'System.Exception'(你是否缺少using指令   或汇编参考?)

我通过执行以下操作修复了它:

if (ex is ServiceException)
{
    var y = (ServiceException)ex;
    ModelState.Merge(y.Errors);
}

有没有办法可以使用变量y来避免这个混乱的代码,然后再投射它?在不声明中间变量y的情况下,代码不会通过语法检查。

3 个答案:

答案 0 :(得分:2)

你需要施放,因为ex不是ServiceExceptionis运算符只是在评估它是否为ServiceException,但不会对该类型执行强制转换。

考虑ex是什么类型。它的类型为Exception,一般来说你不知道它是什么。通过致电ex is ServiceException,您需要检查ex的动态类型是否为ServiceException。但静态类型仍为Exception。这不会改变。

C#是一种静态类型语言,因此ex静态类型Exception在您使用之后不会神奇地更改为ServiceException is运营商。你仍然需要自己施展。

相反,您可能希望使用as运算符:

protected void log(Exception ex)
{
    ServiceException se = ex as ServiceException;
    if (se != null)
        ModelState.Merge(se.Errors);
    else
    {
        Trace.Write(ex);
        ModelState.AddModelError("", "Database access error: " + ex.Message);
    }
}

ex as ServiceException尝试将ex投射到ServiceException。如果ex不是ServiceException,则转换失败并返回null。

或者,如果您真的反对使用额外的局部变量,那么您可以直接使用它然后立即使用它:

if (se is ServiceException)
    ModelState.Merge(((ServiceException) se).Errors);

老实说,虽然我不明白为什么你会这么想。先执行检查(使用asis),然后使用下载的异常,这是最好的选择。实际使用额外变量更加清晰,因为你展示了你的意图,而且你想要实现的目标很明显。

答案 1 :(得分:1)

你需要投射它,但你可以直接进行投射:

if (ex is ServiceException) 
        { 
            ModelState.Merge(((ServiceException)ex).Errors); 
        } 

希望有所帮助:)

答案 2 :(得分:0)

你必须施展,只是我会采用不同的方式。

 try
    {
    ...
    }
    catch(ServiceException ex)
    {
        logException(ex);
    }
    catch(Exception ex)
    {
        logException(ex);
    }

public void logException(ex)
{
    if(ex is ServiceException)
    {
        logServiceException(ex as ServiceException)
    }
    else
    {
        logGenericException(ex)
    }   
}

private void logGenericException(Exception ex)
{
...
}

无需使用以下方法

 private void logServiceException(ServiceException ex)
    {
    //now there is no need to do a cast
    }