我是C#的新手。我有一个隐式的类型变量定义如下:
var item = doc.DocumentNode.SelectNodes("//body[@id='person']")
.Select(p => p.InnerText);
此var有时会返回null
。这就是visual studio要求我处理ArgumentNullException
的地方。但是,如果我这样做,我的var
try
仍然不为我所知catch
- var
,我就再也无法使用它了。
有人建议我使用空对象设计模式,但我不知道我应该如何为{{1}}实现它。有谁知道我应该如何处理这种情况,因为我厌倦了每次都处理空案例。
答案 0 :(得分:2)
我认为,在没有找到结果的情况下,问题是SelectNodes
返回null
。这是我经常遇到的模式:一系列操作,其中一些操作可以返回null
值,其中任何null
的生成应该导致整个序列生成null
。< / p>
一种解决方案是使用函数式程序员调用Maybe
monad的Bind
方法:
public static U IfNotNull<T, U>(this T self, Func<T, U> func)
where U : class
{
return (self != null) ? func(self) : null;
}
这将“传播”空值而不是抛出异常。然后,
doc.DocumentNode
.SelectNodes("//body[@id='person']")
.IfNotNull(nodes => nodes.Select(p => p.InnerText));
如果SelectNodes
返回IEnumerable<XmlNode>
,您可以使用Enumerable.Empty<>
:
(doc.DocumentNode.SelectNodes("//body[@id='person']") ?? Enumerable.Empty<XmlNode>())
.Select(p => p.InnerText);
或者,为了更好的可读性,编写扩展方法以避免担心运算符语法:
public static T Coalesce<T>(this T self, T other)
where T : class
{
return self ?? other;
}
和
doc.DocumentNode.SelectNodes("//body[@id='person']")
.Coalesce(Enumerable.Empty<XmlNode>())
.Select(p => p.InnerText);
这些是推迟空检查的各种方法,直到您准备好处理结果,而不必在扩展方法的情况下捕获NullPointerException
s(或ArgumentException
s)。请注意,如果您在结尾处抛出一个简单的null
运算符,那么产生??
值的任何一个都会产生默认值。
答案 1 :(得分:0)
IEnymerable<HtmlNode> v = null;
var item = doc.DocumentNode.SelectNodes("//body[@id='person']");
if (item != null)
{
v = item.Select(p => p.InnerText);
}