这有什么神奇之处?

Kit*_*124 4 c# xml linq

我最近发现臭名昭着的Jon Skeet关于使用LINQ to XML的帖子.这段特殊代码引起了我的注意:

// 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
    ));
Run Code Online (Sandbox Code Playgroud)

我决定在我的应用程序中自己测试它,我有一个foreach循环设置如下:

foreach (var kvp in m_jobs) {    //m_jobs is a Dictionary<string,Job>
    m_xmlDoc.Root.Element("SCHED_TABLE").Add(
        kvp.Value.GenerateXmlNode())
    );
}
Run Code Online (Sandbox Code Playgroud)

我修改为:

m_xmlDoc.Root.Element("SCHED_TABLE").Add(
    m_jobs.Select(job => job.Value.GenerateXmlNode())
};
Run Code Online (Sandbox Code Playgroud)

其中GenerateXmlNode()是为特定作业项生成适当XML标记的方法.我不确定会发生什么,但是它看起来和我的foreach循环完全一样.我不太明白的是为什么?!此外,这被认为是LINQ的"滥用"还是"功能"?

为清晰起见编辑:我知道.Select将返回一个IEnumerable,其中包含我要求的内容,但我并没有明确地枚举它.我理解.Add是如何工作的,因为它接受了可变数量的参数,但同样,我没有明确枚举传递这些参数.那么......它怎么还能用呢?

Ser*_*rvy 7

这个XElement.Add方法看起来像这样:

public void Add(object content)
{
    if (content is IEnumerable)
    {
        foreach (object child in (IEnumerable)content)
            Add(child);
    }
    else
    {
        //process individual element
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,虽然从公共接口不清楚Add,您可以传递一个项目序列或单个项目,它将确定它在运行时它和相应的行为.


Mar*_*ell 5

没有魔力; 该Add方法接受a object或a params object[]- 并且在内部它只是检查每个输入的一系列常见场景,包括IEnumerable等.然后它只是展开序列,添加它发现的子元素/属性.LINQ返回(在此场景中)IEnumerable序列Select,使其完全可用.