我在公共方法中做的第一件事就是在它们有机会被使用,传递或引用之前验证每个参数,然后在它们中的任何一个违反合同时抛出异常。我发现这是一个非常好的练习,因为它可以让你在违规行为发生的那一刻抓住罪犯,但是,我经常会写一个非常简单的getter / indexer,例如:
private List<Item> m_items = ...;
public Item GetItemByIdx( int idx )
{
if( (idx < 0) || (idx >= m_items.Count) )
{
throw new ArgumentOutOfRangeException( "idx", "Invalid index" );
}
return m_items[ idx ];
}
在这种情况下,index参数直接与列表中的索引相关,而且我知道事实(例如文档)列表本身将完全相同并将抛出相同的异常。我应该删除此验证还是最好不要理会?
我想知道你们的想法,因为我现在正在重构一个大项目,我发现了很多像上面这样的案例。
提前致谢。
答案 0 :(得分:6)
这不仅仅是品味问题,请考虑
if (!File.Exists(fileName)) throw new ArgumentException("...");
var s = File.OpenText(fileName);
这与您的示例类似,但有几个原因(并发,访问权限)OpenText()
方法仍然可能失败的原因,即使出现FileNotFound错误。因此,Exists-check只是给人一种安全和控制的虚假感觉。
这是一个思维定型的东西,当你编写GetItemByIdx方法时,它可能看起来很明智。但是如果你随机查看一段代码,通常会有很多假设你可以在继续之前检查。一遍又一遍地检查它们是不切实际的。我们必须有选择性。
因此,在像GetItemByIdx这样的简单传递方法中,我会反对冗余检查。但是,只要该函数添加了更多功能,或者如果有一个非常明确的规范说明了有关idx的内容,那么参数就会转变。
根据经验,当一个明确定义的条件被破坏并且该条件与当前级别相关时,应抛出异常。如果条件属于较低级别,则让该级别处理它。
答案 1 :(得分:3)
我只会进行参数验证,这会导致代码行为的某些改进。由于您知道,在这种情况下,检查将由List本身执行,因此您自己的检查是多余的,并且不提供额外的值,所以我不会打扰。
答案 2 :(得分:1)
确实可能你复制了已经在API中完成的工作,但它现在已经存在了。如果您的错误处理框架工作且稳定,并且没有导致性能问题(profiling IYF),那么我认为离开它,如果您有时间,请逐步将其逐步淘汰。这听起来不是首要任务!