4

所以我第一次深入研究 Linq to XML(我知道,我落后于时代),到目前为止它非常酷。但是,我遇到了这种非常令人困惑的行为。

我正在解析通用.resx格式。在其中,您有带有 a和 optionaldata的标签。这是我最初尝试的代码:valuecomment

        var items = from str in doc.Root.Descendants("data")
            select new ResourceValue
            {
                Name = str.Attribute("name").Value,
                Value = str.Element("value").Value,
                Comment=str.Element("comment").Value
            };

当然,在我得到元素的地方.valuecomment它会抛出一个空引用异常。好吧,让我们再试一次。我听说您可以将 XElement 转换为字符串,它会神奇地工作。让我们试试

        var items = from str in doc.Root.Descendants("data")
            select new ResourceValue
            {
                Name = str.Attribute("name").Value,
                Value = str.Element("value").Value,
                Comment=str.Element("comment") as string
            };

哦。这次我得到一个编译器错误。

无法通过引用转换、装箱转换、拆箱转换、包装转换或空类型转换将类型“System.Xml.Linq.XElement”转换为“字符串”

好吧,这很奇怪..让我们搜索stackoverflow。瞧,我发现了一个片段,它暗示了这一点:

        var items = from str in doc.Root.Descendants("data")
            select new ResourceValue
            {
                Name = str.Attribute("name").Value,
                Value = str.Element("value").Value,
                Comment=(string)str.Element("comment")
            };

哇。这样可行!?但是,转换null为字符串会引发空引用异常......不是吗?我以为as string正是这种情况!?

这是如何工作的,为什么我可以进行显式转换,但不能进行显式as转换?

4

2 回答 2

9
str.Element("comment") as string

这会检查是否XElement是一个字符串。但这不是真的 -XElement不是从字符串派生的,所以它不是字符串。这就是你有错误的原因。

(string)str.Element("comment")

这是一个重载的运算符,它在Value内部获取属性:

public static explicit operator string(XElement element)
{
    if (element == null)        
        return null;

    return element.Value;
}

它首先检查操作数是否为null,如果是则返回null。这就是为什么你没有例外。


顺便说一句,这些显式转换运算符有一个有趣的地方——它们都不会抛出NullReferenceException,因为它们在访问元素的 Value 属性之前检查元素是否为 null。即使 element 是null并且您正在尝试获取整数,那么您将拥有ArgumentNullException而不是NullReferenceException. 如果null是您要转换为的类型的可接受值(即可为空的类型或字符串),则null返回没有任何异常。这就是为什么使用这些显式转换运算符比访问 Value 属性更安全的原因。

于 2013-08-06T16:03:18.240 回答
0

obj as string - 这是将对象转换为字符串的尝试,它可能会失败也可能不会失败(如果失败,则结果为 null),不会抛出异常。(string)obj - 这是 obj 到字符串类型的显式转换,您告诉编译器 obj 是一个字符串。如果 obj 不是字符串类型,你会得到一个强制转换异常。

请参阅此链接以获取更多信息。- C# 中的转换/转换方法之间的区别

于 2013-08-06T16:06:09.977 回答