-2

我是 C# 的新手。我有一个这样定义的隐式类型变量:

 var item = doc.DocumentNode.SelectNodes("//body[@id='person']")
                                  .Select(p => p.InnerText);

这个 var 有时会返回null. 这就是视觉工作室要求我处理ArgumentNullException. 但如果我这样做,我var的其他人仍然不知道我的try-catch我不能再使用它了。

有人建议我使用空对象设计模式,但我不知道应该如何为var. 有谁知道我应该如何处理这种情况,因为我厌倦了每次都处理 null 情况。

4

2 回答 2

2

我假设,看起来,当没有找到结果时问题又SelectNodes回来了。null这是我经常遇到的一种模式:一系列操作,其中一些可以返回null值,其中 any 的null产生应该导致整个序列产生null.

一种解决方案是使用函数式程序员所称的MaybemonadBind方法:

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);

这些都是推迟空检查的各种方法,直到您准备好处理结果,而不必捕获NullPointerExceptions(或ArgumentExceptions 在扩展方法的情况下)。请注意,如果您在最后抛出一个简单的运算符,则任何产生null值的方法都可能产生默认值??

于 2012-11-07T15:14:18.747 回答
0
IEnymerable<HtmlNode> v = null;    
var item = doc.DocumentNode.SelectNodes("//body[@id='person']");
if (item != null)
{
    v = item.Select(p => p.InnerText);
}
于 2012-11-07T15:03:09.527 回答