假设一个简单的示例,其中方法检索集合(例如包含一些配置字符串的列表)并尝试以某种方式检查它:
void Init()
{
XmlDocument config = new XmlDocument();
config.Load(someXml);
var list = config.SelectNodes("/root/strings/key"); // Normally, list should not be null or empty
if (list == null || list.Count == 0)
throw new SomeExceptionType(message); // What kind of exception to throw?
// Iterate list and process/examine its elements
foreach (var e in list) ...
}
在此特定实例中,如果未检索到任何内容,则该方法无法正常继续。我不确定在这种情况下抛出什么异常类型。据我所知,我的选择是:
您可以为适当的逻辑创建自己的异常类型:
public class InitializationException : Exception
{
}
接着:
throw new InitializationException {Message = "Collection is empty"};
我不确定在这种情况下你可以优雅地抛出一个内置异常... a NullReferenceException
是不合适的,因为空列表不是空引用
我建议使用Dmintry提出的解决方案,因为调用者仍然可以使用 try...catch(Exception)
不必知道或关心异常是真的 SuperDooperListNullOrEmptyFunTimeException
因为从调用者的角度来看这是一个不可恢复的错误(即他们无法控制所选的Xml路径,并且无法控制正在加载的XML),所以异常只会被转储到日志中或在屏幕上供人类消费,此时它没有实际意义 - 因为实际的信息比类型更重要。
另一方面,如果它是可恢复的(调用者可以在确保加载的xml现在包含正确格式化的xml之后重新尝试该方法,或者调用者可以通知用户并要求他们去修复XML并且“你想现在重试吗?“那种事情,那么你 需要 给他们一个打字的例外,这样他们就知道重试是安全的,而不是一个普通的旧例外,这可能意味着其他事情发生了可怕的错误,重试只会让事情变得更糟......
这不是编程问题,因为它是一个设计问题,.NET列表对象在它们为空时不抛出异常的原因是因为很多情况下空列表是可预期和可接受的情况。
如果在上下文中,您使用的列表永远不会为空,则抛出异常(自定义的)
但是,如果列表可能是空的可能且合乎逻辑,那么为什么要中断整个事情,除了例外情况之外,需要例外?一个 foreach
循环和空列表不会抛出异常,循环根本不会循环。
至于零可能性(非常罕见) SelectNodes
如果理解得很好)这是同样的问题,在一些库或函数返回一个 null
是正常的行为而不是例外。