我创建了一个这样的异常类:
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的情况下,代码不会通过语法检查。
答案 0 :(得分:2)
你需要施放,因为ex不是ServiceException
。 is
运算符只是在评估它是否为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);
老实说,虽然我不明白为什么你会这么想。先执行检查(使用as
或is
),然后使用下载的异常,这是最好的选择。实际使用额外变量更加清晰,因为你展示了你的意图,而且你想要实现的目标很明显。
答案 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
}