为什么我可以使用(字符串)而不能使用“字符串”;作为字符串“;在Linq到XML查询中

本文关键字:字符串 Linq XML 查询 我可以 可以使 不能 为什么 | 更新日期: 2023-09-27 18:26:34

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

我正在解析常见的.resx格式。在其中,您有一个data标记,其中包含一个value和一个可选的comment。这是我第一次尝试的代码:

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

当然,在我获得comment元素的.value的地方,它会抛出一个null引用异常。。好吧,让我们再试一次。我听说你可以把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
            };

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

无法通过引用转换、装箱转换、取消装箱转换、包装转换或空类型转换

好吧,这很奇怪。。让我们搜索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强制转换为字符串会引发null引用异常。。。不是吗?我认为as string在这种情况下正是!?

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

为什么我可以使用(字符串)而不能使用“字符串”;作为字符串“;在Linq到XML查询中

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。这就是为什么不会出现异常的原因。


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

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

请参阅此链接以了解更多信息-C#中铸造/转换方法之间的差异