我有一个包含List<>
的类我通过索引方法获得GetValue:
public RenderedImageInfo GetValue(int index)
{
list[index].LastRetrieved = DateTime.Now;
return list[index];
}
如果用户请求的索引超出范围,则会抛出ArgumentOutOfRangeException。
我应该让这件事发生或检查并扔掉我自己的?即。
public RenderedImageInfo GetValue(int index)
{
if (index >= list.Count)
{
throw new ArgumentOutOfRangeException("index");
}
list[index].LastRetrieved = DateTime.Now;
return list[index];
}
在第一个场景中,用户将从内部列表中获得异常,从而打破了用户不需要了解底层对象的OOP目标。
但在第二种情况下,我觉得好像在添加冗余代码。
修改
现在,我想到了,第三种情况,我捕获内部异常,修改它,并重新抛出它?
答案 0 :(得分:12)
你应该抛出自己的,原因有两个:
至于捕获和修改内部异常 - 我不一定会推荐这个。如果异常是额外信息可能有用的异常,则应使用新异常的InnerException来提升此信息。
在这个例子中(ArgumentOutOfRangeException),存在内部列表的事实应该作为实现细节保留,并且您的用户没有理由看到该信息。
答案 1 :(得分:3)
如果您使用的是.NET 2.0或更高版本,则可以使用the inner exception,如下所示:
public RenderedImageInfo GetValue(int index)
{
try {
list[index].LastRetrieved = DateTime.Now;
return list[index];
} catch (ArgumentOutOfRangeException ex) {
throw new ArgumentOutOfRangeException("index", ex);
}
}
这样,您的用户将主要看到您的例外,但如果您(或他们)想要,可以深入挖掘。
编辑:我现在看到自.NET 1.0以来一直支持InnerException
,它只是新构造函数。在2.0之前,我认为没有办法在.NET中为InnerException
实际设置ArgumentOutOfRangeException
。他们只是忘记了它,还是我上面写的代码与预期用途有关?
答案 2 :(得分:3)
...打破m [y]用户不需要知道底层对象的OOP目标。
抛出相同的异常对封装没有任何作用。您的(暗示/记录 - 因为我们没有检查异常或DbC)合同规定您将在这种情况下抛出ArgumentOutOfRange
异常。如何生成该异常,以及它的堆栈跟踪看起来与调用者无关。
如果您将内部实现移动到不抛出ArgumentOutOfRange异常的内容,那么您需要自己抛出一个来履行合同(或对合同进行重大更改)
堆栈跟踪(和param名称)用于调试 - 不用于编程访问。除非存在一些安全问题,否则不要担心让它们“泄密”。
顺便说一下,包装异常的建议(你可能会想到)来自一个更抽象的场景。如果用户不能IAuthenticationService
,,请考虑投出Login
如果同时存在LdapAuthenticationService
和DatabaseAuthenticationService
实现,那么您必须同时捕获LdapDirectoryException
和SqlException
以确定登录失败。完成第三个实现后,您还需要添加它的特定异常类型。所有实施者都将其特定异常包装在FailedAuthenticationException
中,您只需担心单一类型。
尽管在InnerException
中包含原始异常仍然是个好主意,因为它有助于调试。
我希望你能看到这个场景和你的场景之间的区别 - 在你的情况下,你只是抛出相同的异常类型,所以没有区别。
所有这一切,如果它是一个图书馆 - 然后我会检查它并扔掉。但不是因为OOP纯度 - 而是因为它使合同明确,不太可能无意中改变。如果我使用的是[T | B] DD,那么我只是为它编写一个测试,然后让List
抛出 - 测试使合同明确。
答案 3 :(得分:2)
在这种情况下让异常泡沫很好。
修改的
我被要求更新我的答案,以包括一些回复......
可以说,捕获异常并将其重新抛出为内部更加健壮,因为它可以使您与变更隔离并创建更一致的界面。话虽如此,在开发人员可以访问所有代码的环境中,收益可能非常小 - 无人接近。而且,我们获得的任何微小的好处都不是免费的。额外的错误处理代码增加了复杂性,并且必须对其进行测试以确保其有效。它还增加了在维护期间破坏方法的风险,因为所有防弹措施都可能掩盖方法的基本功能。
那么,值得吗?这取决于。它归结为成本/收益分析,只能针对特定环境进行。对于公共API,例如AlphaFS,其好处可能会超过成本。对于非专为重复使用而设计的代码的内部使用,可能不是。这是我原来答案的背景,我仍然坚持。此外,正如Hightechrider所指出的那样,可能还有其他技术,例如编码合同,它们以更低的成本产生相同的好处,改变方程式,有利于稳健性。
与往常一样,我愿意接受理性的分歧。但是,我建议我们都尽量避免一刀切的想法。
修改的
当我说错误处理代码容易出错时,我要说清楚我并不疯狂,看看原来的问题并告诉我你是否能发现错误。如果你这样做,我会提供+1。