举个例子,假设我有一个名字数组,我想通过调用一个带Person
的构造函数来创建一个string name
个对象数组。
class Person()
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
}
...
static void Main()
{
string[] names = {"Peter", "Paul", "Mary"};
Person[] people;
/* I could do this but I'm wondering if there's a better way. */
List<Person> persons = new List<Person>();
foreach(string name in names)
{
persons.Add(new Person(name));
}
people = persons.ToArray();
}
我已经被困在.Net 2.0世界太久了,我正试图在当前的停机时间进行现代化改造......
答案 0 :(得分:57)
// names is string[]
Person[] people = names.Select(s => new Person(s)).ToArray();
说明:
Enumerable.Select
是用于投影的LINQ方法。也就是说,采用一系列Foo
s并通过某些规则Bar
将其投射到Func<Foo, Bar>
s,该规则会Foo
s并吐出Bar
s。因此
names.Select(s => new Person(s))
是类型names
的序列IEnumerable<string>
到类型IEnumerable<Person>
的序列的投影。如果您了解函数式编程,则它将扮演map
。
现在,这里有一个值得理解的微妙点;这几乎肯定是LINQ最重要但容易被误解的方面之一。这是延迟执行的概念。当我们说
IEnumerable<Person> persons = names.Select(s => new Person(s));
这实际上并不执行投影(即,它还没有创建使用Person
中的string
作为构造函数参数构造的names
实例。相反,它会创建一些内容,用于捕获如何将序列names
投影到Person
序列中的规则。只有在实际执行该规则(称为迭代器)时才会进行投影。
导致执行此操作的一种方法是使用方法Enumerable.ToArray
,它基本上会遍历序列并将结果作为数组返回给我。
还有其他方法可以导致执行。例如
IEnumerable<Person> persons = names.Select(s => new Person(s));
foreach(Person p in persons) {
Console.WriteLine(p.Name);
}
或
IEnumerable<Person> persons = names.Select(s => new Person(s));
Person p = persons.First();
将执行“第一个”投影(即new Person(names[0]
))并将结果分配给p
。
当然,这甚至没有达到什么
s => new Person(s)
是。这是一个lambda表达式,您可以在我对How does this LINQ Expression work?的回答中对它们进行介绍。
答案 1 :(得分:1)
我发布此内容时,其他人需要了解略有不同的情况。这是我的情况,我用杰森的答案来到那里。
想象一下,你有一个人的姓名和职位,你想要填写该对象:
public class Employee
{
private string name;
private string jobTitle;
public Employee(){}
public Employee(string name, string job)
{
this.name = name;
this.jobTitle = job;
}
// getters + setters...
}
然后你做
var IQueryable<Employee> list = from p in context.Persons
join j in context.Jobs
on p.jobId == j.jobId
select new Employee(p.Name, j.Title);
然后,您将遍历列表以获取实例