有人可以帮助我改善这个linq

时间:2011-10-26 04:11:43

标签: c# linq

我这里有一个代码,使用linq为Engineer列表生成XML。我的问题是,有没有办法改进和加快这种方法

    public static string CreateXMLforEngineersByLinq(List<Engineers> lst)
    {
        string x = "<Engineers>\n";
        x += string.Concat(lst.Select(s =>
                string.Format("<Engineer>\n<LicenseID>{0}</LicenseID>\n<LastName>{1}</LastName>\n<FirstName>{2}</FirstName>\n<MiddleName>{3}</MiddleName>\n</Engineer>\n", 
                s.LicenseID, s.LastName, s.FirstName, s.MiddleName)));
        return x + "</Engineers>";
    }

结果:

嗨,下面的代码是我添加的,以显示我生成的方法的实际速度更多的答案和修订,再次感谢那些帮助的人:)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using test.Classes;

namespace test.LINQ
{
public static class BatchOperations
{
    delegate string Operations(List<Engineers> i);        
    public static List<int> BatchAddition(List<int> lstNumbers)
    {
        lstNumbers = (from nl in lstNumbers
                      select nl + 2).ToList();

        return lstNumbers;
    }

    public static string CreateXMLforEngineersTheSimpleWay(IEnumerable<Engineers> lst)
    {
        StringBuilder x = new StringBuilder();
        x.AppendLine("<Engineers>");
        foreach (var s in lst)
        {
            x.AppendFormat("<Engineer>\n<LicenseID>{0}</LicenseID>\n<LastName>{1}</LastName>\n<FirstName>{2}</FirstName>\n<MiddleName>{3}</MiddleName>\n</Engineer>\n",
                           s.LicenseID,
                           s.LastName,
                           s.FirstName,
                           s.MiddleName);
        }
        x.AppendLine("</Engineers1>");
        return x.ToString();
    }

    public static string CreateXMLforEngineersByLinq(List<Engineers> lst)
    {
        string x = "<Engineers>\n";
        x += string.Concat(lst.Select(s =>
                string.Format("<Engineer>\n<LicenseID>{0}</LicenseID>\n<LastName>{1}</LastName>\n<FirstName>{2}</FirstName>\n<MiddleName>{3}</MiddleName>\n</Engineer>\n", 
                s.LicenseID, s.LastName, s.FirstName, s.MiddleName)));
        return x + "</Engineers2>";
    }

    public static string CreateXMLforEngineersByLoop(List<Engineers> lst)
    {
        string XmlForEngineers = "<Engineers>";
        foreach (Engineers item in lst)
        {
            XmlForEngineers += string.Format("<Engineer>\n<LicenseID>{0}</LicenseID>\n<LastName>{1}</LastName>\n<FirstName>{2}</FirstName>\n<MiddleName>{3}</MiddleName>\n</Engineer>\n"
                , item.LicenseID, item.LastName, item.FirstName, item.MiddleName);
        }
        XmlForEngineers += "</Engineers3>";
        return XmlForEngineers;
    }

    public static void ShowEngineersByLicense()
    {
        List<Engineers> lstEngr = new List<Engineers>();

        Engineers tom = new Engineers();
        tom.FirstName = "Tom";
        tom.MiddleName = "Brook";
        tom.LastName = "Crook";
        tom.LicenseID = "1343-343434";

        Engineers ken = new Engineers();
        ken.FirstName = "ken";
        ken.MiddleName = "Brook";
        ken.LastName = "Crook";
        ken.LicenseID = "1343-343434";

        Engineers ben = new Engineers();
        ben.FirstName = "ben";
        ben.MiddleName = "Brook";
        ben.LastName = "Crook";
        ben.LicenseID = "1343-343434";

        for (int y = 0; y <= 1000; y++)
        {
            lstEngr.Add(tom);
            lstEngr.Add(ken);
            lstEngr.Add(ben);
        }

        List<Operations> j = new List<Operations>();
        j.Add(a => CreateXMLforEngineersTheSimpleWay(lstEngr));
        j.Add(i => CreateXMLforEngineersByLinq(lstEngr));
        j.Add(i => CreateXMLforEngineersByLoop(lstEngr));

        DateTime start, end;
        TimeSpan diff1 = new TimeSpan();

        foreach (Operations currentMethod in j)
        {
            start = DateTime.Now;
            Console.Write(currentMethod(lstEngr));
            end = DateTime.Now;
            diff1 = end - start;
            Console.WriteLine(diff1);
            Console.Write("\n\n");
        }
    }
}

}

4 个答案:

答案 0 :(得分:3)

使用XmlSerializer,并为方便起见构建扩展方法。

public static class XmlExtensions
{
    public static string ToXml<T>(this T instance)
    {
        var xmlSerializer = new XmlSerializer(typeof(T));
        var stringWriter = new StringWriter();
        xmlSerializer.Serialize(stringWriter, instance);
        return stringWriter.ToString();
    }
}

public static string CreateXMLforEngineersByLinqMyWay(List<Engineers> lst)
{
    return string.Format("<Engineers>{0}</Engineers>"
        , string.Join("",
            lst.Select(s => s.ToXml()) // Might have to put `.ToArray()` here
            )
        );
}

或者你可以这样做:

return lst.ToXml();

如果这是更大的对象树序列化的一部分,那么只需放弃整个方法,并在顶级对象上执行ToXml

您可能需要编辑ToXml方法以使其删除XML命名空间等。

答案 1 :(得分:2)

最明显的加速:使用StringBuilder代替字符串。有关StringBuilder与简单串联相比的性能的全面讨论,请参阅this article

此外,这是一个通过完全取消linq获得更简单,更快速解决方案的案例;

 public static string CreateXMLforEngineersTheSimpleWay(IEnumerable<Engineers> lst)
    {
        StringBuilder x = new StringBuilder();
        x.AppendLine("<Engineers>");
        foreach(var s in lst)
        {
              x.AppendFormat("<Engineer>\n<LicenseID>{0}</LicenseID>\n<LastName>{1}</LastName>\n<FirstName>{2}</FirstName>\n<MiddleName>{3}</MiddleName>\n</Engineer>\n", 
                             s.LicenseID, 
                             s.LastName, 
                             s.FirstName, 
                             s.MiddleName);
        }
        x.AppendLine("</Engineers>");
        return x.ToString();
    }

如果您在Linq上设置了心脏,则可以使用String.Join方法。但是,我怀疑这不会像第一个解决方案那样好,因为下面的解决方案必须创建一个临时数组。

public static string CreateXMLforEngineersByLinq(List<Engineers> lst)
{
    var x = new StringBuilder();
    x.AppendLine("<Engineers>)";
    x.Append(
                string.Join(
                             "\n",
                             lst.Select(s =>
                                string.Format(
                                           "<Engineer>\n<LicenseID>{0}</LicenseID>\n<LastName>{1}</LastName>\n<FirstName>{2}</FirstName>\n<MiddleName>{3}</MiddleName>\n</Engineer>\n", 
                                            s.LicenseID, 
                                            s.LastName, 
                                            s.FirstName, 
                                            s.MiddleName
                                            )
                              ).ToArray()
                        );
      x.AppendLine("</Engineers>");
      return x.ToString();

}

答案 2 :(得分:1)

我认为测试是否使用XmlSeriaizer对整个列表进行序列化并不会更快。

像这样:

using (var fileStream = new FileStream("engineers.xml", FileMode.OpenOrCreate))
{
     var xmlSerializer = new XmlSerializer(typeof(List<Engineer>))
     xmlSerializer.Serialize(fileStream, list);
}

答案 3 :(得分:1)

所有其他示例都使用字符串concat来生成XML。这样做的缺点是,如果您的任何值没有正确地转义XML中不支持的字符(例如&lt;和&amp;),它将会失败。最好使用XML本地工作。请考虑以下事项:

public static string CreateXMLforEngineersByLinq(List<Engineers> lst) 
{ 
    string x = New XElement("Engineers", 
                   lst.Select(new XElement, "Engineer",
                      new XElement("LicenseID", s.LicenseID),
                      new XElement("LastName", s.LastName),
                      new XElement("FirstName", s.FirstName),
                      new XElement("MiddleName", s.MiddleName)
                   )
               );
    return x.ToString();
} 

如果您不想在将其推送到字符串之前花费在内存中创建整个XML的内存开销,您可能需要考虑使用XStreamingElement(http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx)。有关如何使用它的快速视频,请参阅http://www.microsoft.com/uk/msdn/nuggets/nugget/295/LINQ-to-XML-Streaming-Large-Data-Files-Out-of-Memory.aspx