泛型的一点遗憾
发布:张逸 | 发布时间: 2009年2月14日在项目中,我定义了一个ThrowHelper辅助类,用于抛出项目中的自定义异常。例如定义了这样的一个异常:
{
public EmployeeException()
: base()
{ }
public EmployeeException(string message)
: base(message)
{ }
public EmployeeException(string message, Exception innerException)
: base(message, innerException)
{ }
}
我们可以在ThrowHelper中定义抛出该异常的方法,以便于调用者调用:
{
public static EmployeeException ThrowEmployeeException(string message)
{
LogService.Error(message);
throw new EmployeeException(message);
}
public static EmployeeException ThrowEmployeeException(string message, Exception innerException)
{
LogService.Error(message, innerException);
throw new EmployeeException(message, innerException);
}
}
一个问题是当我们定义了多个自定义异常时,我们需要不断地向ThrowHelper添加新的方法。这就像是在记流水账。开发人员不可能喜欢这样的重复劳动。
那么,我们是否可以利用泛型来解决这一问题呢?例如定义该辅助类的泛型版本:
where TCustomException : ApplicationException, new()
{
public static TCustomException ThrowCustomException(string message)
{
LogService.Error(message);
throw new TCustomException(message);
}
public static TCustomException ThrowCustomException(string message, Exception innerException)
{
LogService.Error(message, innerException);
throw new TCustomException(message, innerException);
}
}
可惜,泛型类型并不支持带参的构造函数调用。要解决这一问题,只有使用反射技术。实现如下:
where TCustomException : ApplicationException, new()
{
public static TCustomException ThrowCustomException(string message)
{
LogService.Error(message);
TCustomException exception = (TCustomException)typeof(TCustomException).GetConstructor(new Type[] { typeof(string) }).
Invoke(new object[] { message });
throw exception;
}
public static TCustomException ThrowCustomException(string message, Exception innerException)
{
LogService.Error(message,innerException);
TCustomException exception = (TCustomException)typeof(TCustomException).GetConstructor(new Type[] { typeof(string), typeof(Exception) }).
Invoke(new object[] { message, innerException });
throw exception;
}
}
然而,我总感到非常遗憾,既然泛型的where约束中可以使用new(),那么,为何不能提供带参的构造函数约束呢?例如这样的实现:
where TCustomException : ApplicationException, new(), new(string), new(string, Exception)
{
public static TCustomException ThrowCustomException(string message)
{
LogService.Error(message);
throw new TCustomException(message);
}
public static TCustomException ThrowCustomException(string message, Exception innerException)
{
LogService.Error(message, innerException);
throw new TCustomException(message, innerException);
}
}
不知在将来的C#版本中可否提供这样的泛型支持呢?莫非,实现这样的语法还存在相当的难度?
- 相关文章:
- 1.麒麟.NET
- http://kirinboy.cnblogs.com
- 学习了!居然和我遇到的问题一样,而且居然类名都是一模一样的,呵呵。
因为Exception.Message是只读的,还不能在代码里设置。郁闷了很长时间。谢谢! - 2009-3-3 17:24:18 回复该留言
- 2.opend
- 这样做应该可行
public static void ThrowCustomerException<TCustomException>(TCustomException customException) where TCustomException:ApplicationException
{
//Some Methods
LogService.Error(customException.Message);
throw customException;
}
调用时,传入一个自定义异常的实例。而不是在方法体内实例化。耦合性可能高些。麒麟.NET 于 2009-3-4 9:54:55 回复确实可行,但是ThrowHelper的职责就是生成Exception实例,并且抛出,不仅仅局限于日志记录之类的。如果在调用ThrowHelper的方法之前要实例化Exception,客户端代码没有减少,不能体现设计的初衷。 - 2009-3-4 5:08:01 回复该留言
- 3.Opend
- 代码量变化应该不大,只传参数的话,要声明具体类型,传实例的可以交给编译器判断,我也感觉,你的ThrowHelper本身就有工厂的作用,这样做可能与现有模式不一致,之前想过用静态类解决非这个,结果绕来绕去还是回到泛型构造函数上来了。
- 2009-3-4 19:00:31 回复该留言
- 4.NickWang
- 如果构造一个所有自定义异常的基类,并把LogService.Error(message);这一句加到基类的构造函数中,我觉得就可以解决这个问题了。
- 2009-3-4 22:52:43 回复该留言
发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。






张逸(Bruce Zhang)
