在VB.Net中有IEnumerable<XElement>.Value()扩展方法,但在C#中没有?

4
在VB.Net中,您可以轻松地获取XElement的第一个子元素的文本值,如下所示:
Dim sChildValue = xeParent.<MyChild>.Value()

当然,C#不支持这种语法,但它产生的IEnumerable(Of XElement)结果与Elements()方法相同。因此,我们可以像下面这样重写上面的代码:
Dim sChildValue = xeParent.Elements("MyChild").Value()

这个Value()扩展方法非常方便,因为通常你处理的是小型XML文档,只需要返回第一个匹配的节点。(但是这个方法令我感到困扰的一点是,如果IEnumerable列表为空,由于找不到指定的元素,它似乎会返回Nothing/null。要解决这个问题,我创建了自己的ValueOrBlank()方法,在这种情况下返回一个空字符串。)

我的问题是我无法在C#中做同样的事情:

var sChildValue = xeParent.Elements("MyChild").Value(); // won't compile, can't find Value() method

我检查了我的引用和导入,它们与VB.Net项目匹配,而在该项目中相同的调用有效。幸运的是,我能够使用自定义的ValueOrBlank()扩展方法来完成相同的事情。但我很好奇我的C#项目中缺少什么。我尝试在Visual Studio中右键单击Value()方法调用,然后点击“转到定义”,以查看对象浏览器是否可以告诉我扩展方法存储在哪里,但它只显示System.String类。这是否意味着这是编译器本身支持的那些狡猾的VB.Net专属功能之一,例如XML Axis < MyChild >语法?


它返回“Nothing”而不是空字符串是一种功能,而非错误 -- 由于您正在尝试获取第一个元素的值,而该元素不存在,因此应该引发“对象引用...实例...”异常;但返回“Nothing”相对于这种情况是一个很好的改进,同时仍然允许您区分“无匹配项”和“匹配但没有值”。 - Abacus
@Abacus,严格来说,我同意尝试获取空序列的第一个元素的值应该抛出异常。但是,返回空字符串的Value()扩展方法在许多场景中都是很好的便利,特别是在UI/显示逻辑中渲染可选字段时。 (类似的例子是jQuery的“流畅”样式,其中选择器可以返回空列表,但大多数方法仍然有效,甚至可以链接。)没关系,我能够使用自己的自定义扩展方法来实现相同的功能。 - Jordan Rieger
2个回答

3

.Value()在你提供的链接中描述的不是扩展方法,而是属性,它是特定于VB.net的(就像任何其他轴属性: .、...、@Attribute、(索引器))。


我在任何地方都找不到它的文档,但GSerg找到了:http://msdn.microsoft.com/en-us/library/bb384768.aspx。有趣的是,我一直以为它是一个扩展方法,因为它在Intellisense中显示为其他扩展方法相同的颜色。但你绝对是对的,它被标记为“属性”。 - Jordan Rieger

0
你需要获取一个单独的元素:
var value = parent.Element("MyChild").Value;

2
如果"MyChild"不存在,这与之前的代码不同,将抛出NullReferenceException异常,因为Element将返回null。VB的Value()是一个真正的扩展方法,已经记录在案,可以接受一个序列并返回序列的第一个元素的.Value(如果序列为空,则返回空字符串)。 - GSerg
是的,GSerg,你说得对,这两者不一样。而且感谢你提供了MSDN的链接,我之前找不到官方文档。在我看来,这表明IEnumerable(Of XElement).Value()与XML Axis语法属于同一类别,这是VB.Net特有的(尽管你可以在不改动编译器的情况下轻松实现它)。我将会撰写一个带有这些信息的答案。 - Jordan Rieger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接