对象引用未设置为使用 LINQ C# 的对象实例
本文关键字:对象 实例 LINQ 设置 对象引用 | 更新日期: 2023-09-27 18:00:27
我解决了命名空间问题,但我仍然有错误消息。我认为问题在于将信息放入列表中
IEnumerable<XElement> InvoiceLines = from e in Document.Root
.Element(P + "InvoiceLines")
.Elements(P + "InvoiceLine")
select new XElement("InvoiceLine",
new XAttribute("LineNumber", e.Element(P + "ID").Value),
new XAttribute("ProductName", e.Element(P + "Item").Attribute(P + "Description").Value),
new XAttribute("UnitPriceTaxInclusive", e.Element(P + "UnitPriceTaxInclusive").Value),
new XAttribute("Quantity", e.Element(P + "InvoicedQuantity").Value),
new XAttribute("UnitCode", e.Element(P + "InvoicedQuantity").Attribute(P + "@unitCode").Value));
然后我尝试使用此发票行保存文档,如下所示:
XDocument FinalDocument = new XDocument(
new XElement("Invoice",
new XAttribute("BuyerName", BuyerName),
new XAttribute("SellerName", SellerName),
new XAttribute("IssueDate", IssueDate),
new XAttribute("ID", InvoiceID),
new XElement("InvoiceLines", InvoiceLines)
));
FinalDocument.Save(name);
FinalDocument.Save(Console.Out);
错误告诉我问题出在"选择新的XElement..."在发票行中
.Value
,如果没有找到匹配的元素或属性,可能会导致NullReferenceException
,我建议使用 (string)
强制转换,如果没有找到有效值,这将简单地产生null
,并且 null 合并运算符??
:
IEnumerable<XElement> InvoiceLines =
from e in Document.Root
.Element(P + "InvoiceLines")
.Elements(P + "InvoiceLine")
select new XElement("InvoiceLine",
new XAttribute("LineNumber", (string)e.Element(P + "ID") ?? ""),
new XAttribute("ProductName", (e.Element(P + "Item") != null) ? (string)e.Element(P + "Item").Attribute(P + "Description") ?? "" : ""),
new XAttribute("UnitPriceTaxInclusive", (string)e.Element(P + "UnitPriceTaxInclusive") ?? ""),
new XAttribute("Quantity", (string)e.Element(P + "InvoicedQuantity") ?? ""),
new XAttribute("UnitCode", (string)e.Element(P + "InvoicedQuantity").Attribute(P + "@unitCode") ?? ""));
这行代码对基础数据有很多假设。 例如,这个:
e.Element(P + "Item").Attribute(P + "Description").Value
该代码段假定:
-
e
保证包含与元素匹配的P + "Item"
- 保证该元素包含与
P + "Description"
匹配的属性
这些假设贯穿了整条线。 因此,如果遇到不符合这些假设的数据,.Element()
或.Attribute()
可能会返回null
,在这种情况下,下一个.
(例如在.Value
中(将尝试取消引用null
值,从而导致该错误。
要添加一些空值检查,您可以将其分成多行代码或将其全部内联。 这两种方法的可读性和可维护性都取决于您。 例如,对于此段:
new XAttribute("LineNumber", e.Element(P + "ID").Value)
您可以添加一些错误检查,如下所示:
new XAttribute("LineNumber",
(e == null ? string.Empty :
(e.Element(P + "ID") == null ? string.Empty :
e.Element(P + "ID").Value)))
我可以看到这可能非常不可读的地方。 您也许可以消除第一次检查,假设e
本身永远不会null
。 但是您的其他细分仍将有一些嵌套检查。
若要将其分开,必须遍历值,而不是使用单个 LINQ 语句。 像这样的结构:
var InvoiceLines = new List<XElement>();
foreach (var e in Document.Root.Element(P + "InvoiceLines").Elements(P + "InvoiceLine"))
{
// build an XElement object from e and add it to the list
}
这不是 100% 相同的,因为它急切地加载整个集合。 因此,您也可以将循环本身分离到另一个返回IEnumerable<XElement>
的方法中,并使用yield return
不必急于加载整个内容。 这取决于你。
想想看,您最初的数据选择器也会做出假设:
Document.Root.Element(P + "InvoiceLines").Elements(P + "InvoiceLine")
您可能还希望在此处添加null
检查,以防万一您收到与这些谓词不匹配的数据。
文档中可能不存在您的某些元素或属性。例如:
e.Element(P + "ID").Value
如果没有元素P + "ID"
则上面的行将在访问null
引用的 Value
属性时引发NullReferenceException
。您可能需要执行以下操作
e.Element(P + "ID") ?? 0
其中 0 是您希望它具有的默认值。或者你可以用一个老式的for
循环和一些if
循环来做到这一点。