如果列表/集合为空或 null 且无法迭代(不是参数),则引发的异常类型
本文关键字:参数 类型 异常 迭代 集合 列表 null 如果 | 更新日期: 2023-09-27 18:30:22
假设一个简单的示例,其中方法检索集合(例如包含一些配置字符串的列表)并尝试以某种方式检查它:
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) ...
}
在此特定实例中,如果未检索任何内容,则该方法无法正常继续。我不确定在这种情况下要抛出哪种异常类型。据我所知,我的选择是:
手动投掷任何东西,
NullReferenceException
被抛出自动(不处理空列表情况),抛出自定义异常类型(可能不是一个好主意,因为我预计调用者不会尝试对异常做任何事情,即他不会寻找一个特殊的异常类型来处理),
- 做点别的?
如果集合为空,Enumerable.First
会抛出System.InvalidOperationException
。我猜你也可以。
throw new InvalidOperationException("Sequence contains no elements");
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.first?view=netframework-4.8
您可以为适当的逻辑创建自己的异常类型:
public class InitializationException : Exception
{
}
然后:
throw new InitializationException {Message = "Collection is empty"};
我不确定在这种情况下您可以优雅地抛出一个内置异常......NullReferenceException
是不合适的,因为空列表不是空引用
我建议使用 Dmintry 提出的解决方案,因为调用者仍然可以只使用try...catch(Exception)
,而不必知道或关心异常是否确实是一个SuperDooperListNullOrEmptyFunTimeException
由于从调用者的角度来看,这是一个不可恢复的错误(即他们无法控制选定的 Xml 路径,也无法控制正在加载的 XML),因此异常只会被转储到日志或屏幕上供人类使用,此时它没有意义 - 因为实际消息比类型更重要。
另一方面,如果它是可恢复的(调用方可以在确保要加载的 xml 现在包含格式正确的 xml 后重试该方法,或者调用方可以通知用户并要求他们去修复 XML 和"你想现在重试吗?"之类的事情),那么你需要给他们一个类型化的异常,以便他们知道重试是安全的,而不是普通的旧异常可能意味着其他事情出了可怕的错误,重试只会让事情变得更糟......
太多的编程问题,因为它是一个设计问题,.NET 列表对象在它们为空时不会引发异常的原因是,在很多情况下,空列表是预期和可接受的情况。
如果在上下文中您使用的列表永远不应该为空,则抛出异常(自定义异常)
但是,如果该列表可能是空的并且合乎逻辑,为什么要中断整个事情,它除外不是例外,所以需要一个例外?foreach
循环和空列表不会引发异常,循环根本不会循环。
至于空的可能性(如果理解得很好,对于SelectNodes
来说非常罕见),这是同样的问题,在某些库或函数中,返回null
是一种正常行为而不是例外。