【发布时间】:2013-02-04 15:15:26
【问题描述】:
我最近看到了臭名昭著的 Jon Skeet 关于使用 LINQ to XML 的帖子。这段特殊的 sn-p 代码引起了我的注意:
// Customers is a List<Customer>
XElement customersElement = new XElement("customers",
customers.Select(c => new XElement("customer", //This line is "magic"
new XAttribute("name", c.Name),
new XAttribute("lastSeen", c.LastOrder)
new XElement("address",
new XAttribute("town", c.Town),
new XAttribute("firstline", c.Address1),
// etc
));
我决定在我的应用程序中自己测试它,我设置了一个 foreach 循环,如下所示:
foreach (var kvp in m_jobs) { //m_jobs is a Dictionary<string,Job>
m_xmlDoc.Root.Element("SCHED_TABLE").Add(
kvp.Value.GenerateXmlNode())
);
}
我修改为:
m_xmlDoc.Root.Element("SCHED_TABLE").Add(
m_jobs.Select(job => job.Value.GenerateXmlNode())
};
GenerateXmlNode() 是一种为特定作业项生成适当 XML 标记的方法。我不确定会发生什么,但你瞧,它的工作原理与我的 foreach 循环完全一样。我不太明白的是为什么?!另外,这被认为是 LINQ 的“滥用”还是“功能”?
为清楚起见进行编辑:我知道 .Select 将返回一个 IEnumerable,其中包含我所要求的内容,但我没有明确列举它。我了解 .Add 的工作原理,因为它接受可变数量的参数,但同样,我没有明确列举传递这些参数。那么......它仍然如何工作?
【问题讨论】:
-
为什么什么?考虑到
XElement.Add的广告用途,这段代码有什么令人惊讶的地方? -
@JoelEtherton 实际上,这令人惊讶。方法重载是
Add(Object),而不是Add(IEnumerable<object>)。你怎么知道它需要一个序列或单个项目,而不仅仅是单个项目? -
@PaulBellora 谢谢,完成。
-
@JoelEtherton 你的意思是什么?通常,从方法的公共 API 中应该可以清楚地看出它是接受序列还是单个项目。有一个
object类型的参数来确定该类型是否实现IEnumerable并在实现时采取不同的行为,这是非常 奇怪和意外的。我知道我没想到,我预计pubic void Add(IEnumerable objects)的方法会额外重载。 -
@Servy:我很抱歉。我粘贴了错误的链接。这个链接描述了为什么它并不令人惊讶:msdn.microsoft.com/en-us/library/bb943882.aspx。如果你 RTM,你会看到它表明可以传入复杂的内容:
Any type that implements IEnumerable。