C# 高效地创建列表<;B类>;从列表<;ClassA>;?

C# 高效地创建列表<;B类>;从列表<;ClassA>;?,c#,list,constructor,C#,List,Constructor,我有来自ClassA的对象,希望使用它们来创建ClassB的对象。如果我一次只处理一个对象,我知道怎么做: ClassA object1 = new ClassA(); ClassB object2 = new ClassB(object1); class ClassA { public DateTime Timestamp; public double X; public double Y; public double Z; public Class

我有来自ClassA的对象,希望使用它们来创建ClassB的对象。如果我一次只处理一个对象,我知道怎么做:

ClassA object1 = new ClassA();
ClassB object2 = new ClassB(object1);

class ClassA
{
    public DateTime Timestamp;
    public double X;
    public double Y;
    public double Z;

    public ClassA()
    {
       // other stuff
    }
}

class ClassB
{
    public DateTime Timestamp;
    public double X;

    public ClassB(ClassA A)
    {
        Timestamp = A.Timestamp;
        X = A.X;
    }
}
然而,我正在寻找最好的方法来处理对象列表。我想获取ClassA类型的列表,并创建ClassB类型的列表:

List<ClassA> list_of_classA = new List<ClassA>();
List<ClassB> list_of_classB = ????
List List\u of_classA=new List();
列出类别B的列表=????

您可以使用Linq将列表投影到类型为
ClassB
的新列表中:

List<ClassB> list_of_classB = (from x 
                               in list_of_classA
                               select new ClassB(x)).ToList();
List\u of_classB=(从x开始)
在类别A的列表中
选择new ClassB(x)).ToList();

首先,您可以在Linq上找到许多好的示例。

除了Markus演示的查询样式语法之外,您还可以使用lambda样式语法将ClassA列表投影到ClassB

var listOfClassB = list_of_classA.Select(x => new ClassB(x)).ToList()

只是想用第三种方法来实现这一点:

List<ClassA> list_of_classA = new List<ClassA>();
List<ClassB> list_of_classB = new List<ClassB>();

foreach (ClassA item in list_of_classA)
        {
            list_of_classB.Add(new ClassB(item));
        }
List List\u of_classA=new List();
List List of_classB=新列表();
foreach(类别A列表中的类别A项目)
{
添加(新类别B(项目));
}

这将在不使用Linq或Lambda表达式的情况下完成相同的任务。如果可能,您很可能希望使用提供的其他两个答案中的一个。但是,如果您不熟悉Linq或Lambda表达式,这可能会有所帮助。

您很可能希望按照其他人的建议使用Select

这就是说,如果您只想做列表转换,而性能非常重要,那么List有一个方法,您可以使用它

List<ClassA> list_of_classA = new List<ClassA>();
List<ClassB> list_of_classB = list_of_classA.ConvertAll((ClassA a) => new ClassB(a));
List List\u of_classA=new List();
List_of_classB=List_of_classA.ConvertAll((classA a)=>新classB(a));
您可以阅读有关使用Select和ConvertAll之间差异的更多信息 在性能方面以及在其他方面的差异方面

由于ConvertAll是不太通用的选项(仅适用于列表),因此它应该比更通用的Select选项更快。我试图通过做一些测试来反驳这个观点

我在a-list中创建了一个包含500万和1000万个对象的列表,并测试了ConvertAll和Select选项,得到了以下结果:

其中y轴以毫秒为单位

因此,数据似乎表明ConvertAll实际上要快一点。然而,我的代码可能存在一些导致这些差异的问题,因此对此持保留态度

这是我使用的代码。编译后发布到x64。(还修改了ListA,使其实际上具有正确的构造函数)

使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
名称空间lekstuga
{
班级计划
{
静态void Main(字符串[]参数)
{
int循环=10000000;
对于(var n=0;n<4;n++)
{
秒表;
List listOfClassA2=新列表();
List listOfClassB2=新列表();
for(int i=0;inew ClassB(a));
秒表;
Console.WriteLine(“ConvertAll”+stopwatch.elapsedmillyses+“ms”);
List listOfClassA=新列表();
List listOfClassB=新列表();
for(int i=0;inewclassb(x)).ToList();
秒表;
Console.WriteLine(“选择”+stopwatch.ElapsedMilliseconds+“毫秒”);
}
Console.ReadLine();
}
甲级
{
公共日期时间戳;
公共双X;
公共双Y;
公共双Z;
公共类A(日期时间t,双x,双y,双z)
{
时间戳=t;
X=X;
Y=Y;
Z=Z;
}
}
B类
{
公共日期时间戳;
公共双X;
公共B类(A类)
{
时间戳=A.时间戳;
X=A.X;
}
}
}
}

最后,关于Select的一个注意事项是,虽然它是惰性的,并且在实际需要使用.ToList()之前不会执行,但它会强制LINQ立即计算数据,因此Select和ConvertAll在这方面是可比较的。

假设使用相同的构造函数,您可以
列出\u classA.Select(classA=>new ClassB(classA)).ToList()
?谢谢。根据System.Diagnostics.StopWatch,就我而言,该方法运行良好,速度与其他方法一样快。现在开始阅读lambda风格的语法。谢谢
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace lekstuga
{
    class Program
    {
        static void Main(string[] args)
        {
            int loops = 10000000;

            for (var n = 0; n < 4; n++)
            {

                Stopwatch stopwatch;

                List<ClassA> listOfClassA2 = new List<ClassA>();
                List<ClassB> listOfClassB2 = new List<ClassB>();

                for (int i = 0; i < loops; i++)
                {
                    listOfClassA2.Add(new ClassA(DateTime.Now, 1, 2, 3));
                }

                stopwatch = Stopwatch.StartNew(); //creates and start the instance of Stopwatch
                listOfClassB2 = listOfClassA2.ConvertAll((ClassA a) => new ClassB(a));
                stopwatch.Stop();

                Console.WriteLine("ConvertAll " + stopwatch.ElapsedMilliseconds + "ms");


                List<ClassA> listOfClassA = new List<ClassA>();
                List<ClassB> listOfClassB = new List<ClassB>();

                for (int i = 0; i < loops; i++)
                {
                    listOfClassA.Add(new ClassA(DateTime.Now, 1, 2, 3));
                }

                stopwatch = Stopwatch.StartNew(); //creates and start the instance of Stopwatch
                listOfClassB = listOfClassA.Select(x => new ClassB(x)).ToList();
                stopwatch.Stop();

                Console.WriteLine("Select " + stopwatch.ElapsedMilliseconds + "ms");
            }
            Console.ReadLine();
        }

        class ClassA
        {
            public DateTime Timestamp;
            public double X;
            public double Y;
            public double Z;

            public ClassA(DateTime t, double x, double y, double z)
            {
                Timestamp = t;
                X = x;
                Y = y;
                Z = z;
            }
        }

        class ClassB
        {
            public DateTime Timestamp;
            public double X;

            public ClassB(ClassA A)
            {
                Timestamp = A.Timestamp;
                X = A.X;
            }
        }
    }
}