我需要将数据从一个列表转换为另一个列表。我需要我的代码看起来完全像那样(只是我必须完成的要求):
public interface IHuman
{
string name { get; set; }
string lastName { get ;set; }
int age { get; set; }
}
我还有其他两个课程:
public class HumanA : IHuman
{
//Implementation
}
public class HumanB : IHuman
{
//Implementation
}
在我的计划中,我有这个部分:
List<HumanA> listA = some data
我需要将HumanA列表中的数据写入HumanB列表,它必须是此列表中没有其他组合。
有没有比这更简单的方法:
list<HumanB> listB = listA.ConverAll(x => new HumanA()
{
name = x.name,
lastName = x.lastName,
age = x.age
});
应该是因为HumanA和HumanB只有IHuman的属性实现但是我不能使用:
list<IHuman>
答案 0 :(得分:2)
如果您想要在运行时方面采用更快方式,您希望避免linq的任何开销,并尽可能地集中精力来限制所需的操作。
这意味着您要避免:
List
- 对象因此,您希望使用for
- 循环来获取对象,这样您就没有任何迭代器对象,并且您希望创建具有指定容量的新列表,因此不必调整大小。您还想使用构造函数参数设置所需的属性。
除了创建lambda函数(用作转换器)之外,这与ConvertAll
- 函数的作用完全相同。所以你不会得到任何比这更快的东西。
如果您想获得一些更简单的代码,建议您实现一个构造函数,该构造函数在两个类中都采用IHuman
接口并在那里复制数据。因此,您可以将代码缩减为:
List<HumanB> listB = listA.ConvertAll(x => new HumanB(x));
编辑: 如果我们讨论的是大规模的大型列表和需要相当长时间创建的对象,那么还可以使用多个线程来加快速度。但是对于你提供的简单例子,我非常怀疑这会做什么,只会让事情变得更慢,更复杂。
答案 1 :(得分:2)
Nitram给了你一个非常好的答案,所以我无法提供有关工作代码的更多有用的答案。 BUT
我写了一个小测试,这样你就可以看到自己有什么作用,以及差异是多么微妙。
对测试的一点澄清。
这里的代码:
static void Main(string[] args)
{
//Creation
List<HumanA> listA = new List<HumanA>();
for (int j = 0; j < 2000; j++)
{
listA.Add(new HumanA());
listA.Add(new HumanA());
listA.Add(new HumanA());
listA.Add(new HumanA());
listA.Add(new HumanA());
}
Stopwatch stop = new Stopwatch();
List<HumanB> listB = null;
int roundsToComplete = 10;
long testTime1 = 0;
long testTime2 = 0;
long testTime3 = 0;
long testTime4 = 0;
long testTime5 = 0;
long testTime6 = 0;
long testTime1ms = 0;
long testTime2ms = 0;
long testTime3ms = 0;
long testTime4ms = 0;
long testTime5ms = 0;
long testTime6ms = 0;
for (int rounds = 0; rounds < roundsToComplete; rounds++)
{
//Test 1
stop.Start();
listB = new List<HumanB>();
foreach (HumanA humanA in listA)
{
HumanB humanB = new HumanB();
humanB.age = humanA.age;
humanB.name = humanA.name;
humanB.lastName = humanA.lastName;
listB.Add(humanB);
}
stop.Stop();
testTime1 += stop.ElapsedTicks;
testTime1ms += stop.ElapsedMilliseconds;
listB.Clear();
listB = null;
stop.Reset();
//Test 2
stop.Start();
listB = new List<HumanB>();
foreach (HumanA humanA in listA)
{
HumanB humanB = new HumanB(humanA);
listB.Add(humanB);
}
stop.Stop();
testTime2 += stop.ElapsedTicks;
testTime2ms += stop.ElapsedMilliseconds;
listB.Clear();
listB = null;
stop.Reset();
//Test 3
stop.Start();
listB = listA.ConvertAll(x => new HumanB(x));
stop.Stop();
listB.Clear();
listB = null;
testTime3 += stop.ElapsedTicks;
testTime3ms += stop.ElapsedMilliseconds;
//Test 4
stop.Start();
int count = listA.Count;
listB = new List<HumanB>();
for (int i = 0; i < count; i++)
{
listB.Add(new HumanB(listA[i]));
}
stop.Stop();
listB.Clear();
listB = null;
testTime4 += stop.ElapsedTicks;
testTime4ms += stop.ElapsedMilliseconds;
//Test 5
stop.Start();
listB = listA.Select(x => new HumanB() { name = x.name, lastName = x.lastName, age = x.age }).ToList();
stop.Stop();
listB.Clear();
listB = null;
testTime5 += stop.ElapsedTicks;
testTime5ms += stop.ElapsedMilliseconds;
//Test6
stop.Start();
count = listA.Count;
listB = new List<HumanB>(count);
Parallel.For(0, count, c=>
{
listB.Add(new HumanB(listA[c]));
});
stop.Stop();
listB.Clear();
listB = null;
testTime6 += stop.ElapsedTicks;
testTime6ms += stop.ElapsedMilliseconds;
}
Console.WriteLine("1: " + testTime1 / roundsToComplete);
Console.WriteLine("2: " + testTime2 / roundsToComplete);
Console.WriteLine("3: " + testTime3 / roundsToComplete);
Console.WriteLine("4: " + testTime4 / roundsToComplete);
Console.WriteLine("5: " + testTime5 / roundsToComplete);
Console.WriteLine("6: " + testTime6 / roundsToComplete);
Console.WriteLine("milliseconds 1: " + testTime1ms / roundsToComplete);
Console.WriteLine("milliseconds 2: " + testTime2ms / roundsToComplete);
Console.WriteLine("milliseconds 3: " + testTime3ms / roundsToComplete);
Console.WriteLine("milliseconds 4: " + testTime4ms / roundsToComplete);
Console.WriteLine("milliseconds 5: " + testTime5ms / roundsToComplete);
Console.WriteLine("milliseconds 6: " + testTime6ms / roundsToComplete);
Console.ReadLine();
}
以下是以滴答和毫秒为单位的结果
1: 24944
2: 4278
3: 2746
4: 5003
5: 9230
6: 21502
milliseconds 1: 12
milliseconds 2: 1
milliseconds 3: 0
milliseconds 4: 2
milliseconds 5: 4
milliseconds 6: 10
答案 2 :(得分:0)
目前还不清楚为什么你必须让你的代码看起来和你一样,就像你说的那样。
在实现界面时,您实际上可以使用下面的代码来获得相同的结果。有效地,HumanA和HumanB是相同的,因为您可以执行以下操作,并将listA和listB定义为IHuman列表,然后将HumanA添加到列表中。
var listA = new List<IHuman>();
listA.Add(new HumanA());
listA.Add(new HumanA());
listA.Add(new HumanA());
var listB = new List<IHuman>(listA);
var humanB = (HumanB)listB[0];
实际上并不需要最后一个CAST行,因为该类实现了与HumanA类相同的所有方法,因为IHuman,除非HumanB有额外的方法,否则需要使用强制转换来访问这些方法。
答案 3 :(得分:-3)
试试这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<HumanA> aS = new List<HumanA>();
List<HumanB> bS = aS.Select(x => new HumanB() { name = x.name, lastName = x.lastName, age = x.age }).ToList();
}
}
public class IHuman
{
public string name { get; set; }
public string lastName { get ;set; }
public int age { get; set; }
}
public class HumanA : IHuman
{
//Implementation
}
public class HumanB : IHuman
{
//Implementation
}
}