C#:在给定构造函数参数数组的情况下,是否有 LINQ 方法来创建对象数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2113115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#: Is there a LINQ way to create an array of objects given an array of constructor parameters?
提问by Austin Salonen
As an example, say I have an array of names and I want to create an array of Person
objects by calling a constructor that takes string name
.
例如,假设我有一个名称数组,并且我想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();
}
I've been stuck in the .Net 2.0 world for too long now and I'm trying to modernize in my current downtime...
我已经被 .Net 2.0 世界困住太久了,我正在尝试在当前的停机时间内实现现代化......
采纳答案by jason
// names is string[]
Person[] people = names.Select(s => new Person(s)).ToArray();
Explanation:
解释:
Enumerable.Select
is the LINQ method for projection. That is, taking a sequence of Foo
s and projecting them to Bar
s via some rule Func<Foo, Bar>
that eats Foo
s and spits out Bar
s. Thus
Enumerable.Select
是用于投影的 LINQ 方法。也就是说,取一系列Foo
s 并Bar
通过某种规则Func<Foo, Bar>
将它们投影到s 中,该规则吃掉Foo
s 并吐出Bar
s。因此
names.Select(s => new Person(s))
is a projection of the sequence names
of type IEnumerable<string>
to a sequence of type IEnumerable<Person>
. If you know functional programming it plays the role of map
.
是序列的投影names
类型的IEnumerable<string>
到类型的序列IEnumerable<Person>
。如果您了解函数式编程,它会扮演map
.
Now, there is a subtle point here that is worth understanding; this is almost surely one of the most important yet easily misunderstood aspects of LINQ. This is the concept of deferred execution. When we say
现在,这里有一个微妙的点值得理解;这几乎可以肯定是 LINQ 最重要但最容易被误解的方面之一。这就是延迟执行的概念。当我们说
IEnumerable<Person> persons = names.Select(s => new Person(s));
this does not actually perform the projection (i.e., it does not yet create the instances of Person
constructed using the string
s in names
as constructor parameters). Instead, it creates something that captures the rule of how to project the sequence names
into a sequence of Person
. It's only when that rule (known as an iterator) is actually executed does the projection take place.
这实际上并不执行投影(即,它尚未创建Person
使用string
snames
作为构造函数参数的constructed实例)。相反,它创建了一些捕获如何将序列投影names
到Person
. 只有在实际执行该规则(称为迭代器)时才会进行投影。
One way to cause this execution to occur is to use the method Enumerable.ToArray
which basically says iterate through the sequence and give me back the results as an array.
导致这种执行发生的一种方法是使用Enumerable.ToArray
基本上说遍历序列并将结果作为数组返回给我的方法。
There are other ways to cause the execution to occur. For example
还有其他方法可以导致执行发生。例如
IEnumerable<Person> persons = names.Select(s => new Person(s));
foreach(Person p in persons) {
Console.WriteLine(p.Name);
}
or
或者
IEnumerable<Person> persons = names.Select(s => new Person(s));
Person p = persons.First();
which would execute the "first" projection (i.e., new Person(names[0]
)) and assign the result to p
.
这将执行“第一个”投影(即new Person(names[0]
))并将结果分配给p
。
Of course, this doesn't even get into exactly what
当然,这甚至没有涉及到底是什么
s => new Person(s)
is. That's a lambda expression, and you can get an introduction to them in my answer to How does this LINQ Expression work?.
是。这是一个 lambda 表达式,您可以在我对这个 LINQ 表达式如何工作的回答中获得对它们的介绍。.
回答by Ricardo Appleton
I'm posting this incase someone else needs a light on a slightly different scenario. This was my case, and I used Jason's answer to get there.
我发布此内容以防其他人需要了解略有不同的情况。这是我的情况,我使用 Jason 的回答来实现。
Imagine you have a class with the person's name, and job title, and you want to fill that object:
想象一下,您有一个包含此人姓名和职位的类,并且您想要填充该对象:
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...
}
Then you'd do
然后你会做
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);
Then you'll loop through the list to get the instances
然后您将遍历列表以获取实例