所以我第一次潜入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
};
当然,在我获得.value
元素的comment
的情况下,它会抛出一个空引用异常..好吧,让我们再试一次。我听说你可以将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
};
哦。这次我得到编译器错误。
无法通过a将类型'System.Xml.Linq.XElement'转换为'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
强制转换为字符串会抛出空引用异常......不是吗?对于这种情况,我认为as string
完全!
这是如何工作的,为什么我可以进行显式演员,但不能进行明确的as
演员表演?
答案 0 :(得分: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
。这就是为什么你没有例外。
BTW 这些显式的强制转换运算符很有趣 - 它们都不会抛出NullReferenceException
,因为它们在访问它的Value属性之前检查了null为null。即使元素为null
并且您尝试获取整数,也会使用ArgumentNullException
而不是NullReferenceException
。如果null
是您要转换的类型的可接受值(即可空类型或字符串),则返回null
,没有任何例外。这就是使用这些显式转换运算符比访问Value属性更安全的原因。
答案 1 :(得分:0)
obj as string - 这是尝试将对象转换为字符串,可能会或可能不会失败(如果失败,结果为null),则不会抛出任何异常。 (string)obj - 这是obj对类型字符串的显式转换,你告诉编译器obj是一个字符串。如果obj不是字符串类型,您将获得强制转换异常。
请参阅此链接以获取进一步的见解.- Difference between casting/conversion methods in C#