C#:有一个LINQ方法来创建一个给定一个构造函数参数数组的对象数组?

举个例子说,我有一个名字数组,我想通过调用一个构造函数来创建一个Person对象数组,该构造函数接受字符串名称。

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世界太久了,我试图在我目前的停机时间进行现代化改造…

最佳答案
// names is string[]
Person[] people = names.Select(s => new Person(s)).ToArray();

说明:

Enumerable.Select是用于投影的LINQ方法。也就是说,采取一系列Foos并通过一些规则Func&Foo,Bar>将它们投射到酒吧。吃屎,吐出酒吧。从而

names.Select(s => new Person(s))

是IEnumerable类型的序列名称的投影< string>到IEnumerable< Person>类型的序列。如果你知道功能编程,它起到地图的作用。

现在,这里有一个微妙的一点值得我们了解;这几乎肯定是LINQ最重要但容易被误解的方面之一。这是延期执行的概念。当我们说

IEnumerable<Person> persons = names.Select(s => new Person(s));

这实际上并不执行投影(即,它尚未创建使用名称中的字符串构造为构造函数参数的Person实例)。相反,它会创建一些捕获如何将序列名称投影到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();

这将执行“第一”投影(即新的Person(名称[0]))并将结果分配给p。

当然,这甚至没有达到什么

s => new Person(s)

是。这是一个lambda表达式,您可以在How does this LINQ Expression work?的答案中介绍他们。

转载注明原文:C#:有一个LINQ方法来创建一个给定一个构造函数参数数组的对象数组? - 代码日志