浏览:200 2008-09-10 19:22 来自 【高级组员】Gray Zhang      :

前段时间在某篇博文中与园友就异常的问题进行过激烈的讨论,看我的博客就知道我是个异常的支持者,但看到非常非常多的人不喜欢异常,因此还来向大家请教一下这个问题

 

现在对于异常通常有2种理论:

1.异常非常地消耗资源,因此能不用就不用,不要用异常控制流程,也不要随便抛出异常

2.异常是面向对象中非常重要的概念,用于对错误的统一通知,因此有错误时应该抛出异常

 

假设有以下方法

 

Code
public class User
{
public int ID { get; set; } //自增
public string Name { get; set; }
}

public class UserLogic
{
public User InsertUser(User user)
{
//
}
}

 

 

在代码中,由于User的ID为自增列,因此在Insert之后为了获取数据库自动生成的ID,InsertUser必须返回一个User的对象(也许在本地调用的时候可以自用引用传值来获取ID,但是在分布式环境下必须这样设计)

 

 

对于上面提到的2种异常观点的第1种观点,他们认为InsertUser这个方法完全不应该抛出异常,其实现可能如此

 

Code
if (user == null) return null;
if (user.Name == null) return null;
string sql = "";
try
{
SqlHelper.ExecuteNonQuery(sql);
//执行SQL
}
catch (SqlException)
{
return null;
}

 

 

而对于第2种观点,则认为应该由异常通知具体错误,实现可能如下

 

Code
if (user == null)
throw new ArgumentNullException("用户不能为null");
if (user.Name == null)
throw new ArgumentException("用户名不能为空");
string sql = "";
try
{
SqlHelper.ExecuteNonQuery(sql);
}
catch (SqlException ex)
{
throw new InvalidOperationException(ex.Message);
}

在这个方法中为了不让上层感知到SqlException的存在,特意catch了SqlException并改为InvalidOperationException,使得封装性更强

 

 

从基本的实现可以看出,不使用异常的情况下,没有办法得知传入的user到底有什么问题,假设User类还有Age, Address等字段,仅仅依靠返回值根本无法判断哪一个字段有问题

而使用异常自然要消耗一定的资源,但却可以非常明确地告知调用者出错的原因

 

持第1种意见的人往往又认为,可以包装返回值来实现错误的通知,这时他们往往会将方法签名改掉

 

Code
public class InsertUserResult
{
public string Message { get; set; }
public bool IsSuccessful { get; set; }
public User Result { get; set; }
}

public InsertUserResult InsertUesr(User user);

但是这样做的问题有:

 

1.Message依旧无法很好地告知哪一个字段出问题,客户端无法根据Message来订制错误信息,除非调用者与设计者就Message属性的取值有事先的约定,但是设计并不应该依赖于这种约定

2.也许每一个方法都需要一个XxxResult类来封装,也许可以使用泛型生成一个ExecuteResult<T>的类,但是这种 封装已经完全脱离了业务逻辑的核心,使得接口的设计并没有体现出业务的逻辑,对一开始的建模产生了影响,同时接口也不够优雅、美观

 

个人认为,异常不应该因为其在性能上带来的损失而被放弃,异常真正的优势在于提供一个统一的错误通知的方案,而这个优势根本不是其他设计能够弥补的,不知大家对一这个问题有没有什么想法,到底是不是应该在这种情况下使用异常,应该如何使用,对于异常的使用又有什么准则?

收藏 楼主
  2个月前 【组长】 kunkun      :
呵呵,现在也会做广告了哦!顶一个。
1楼 回到顶楼 
  2个月前 【高级组员】 Gray Zhang      :
找不到一个合适地小组来放这样的帖子……应该有个.NET General之类的小组哦
2楼 回到顶楼 
  1个月前  Doho      :
个人认为:异常是一个非常好的消息通信机制,在.NET Framework里到处都可以看到异常,对异常的使用也是有讲究的,如果你是一位类库开发人员,在不符合逻辑的地方就要抛出异常;如果你是一位UI开发人员,为了给用户一个好的体验,你就不能抛出异常,而是给一个友好的提示:比如文章中说的 用户名不能为空。
3楼 回到顶楼 

注册用户登录后才能回复,登录注册
> 返回“.NET 新手小组”


其他话题

相关内容

相关链接
1 31019