C#:在给定构造函数参数数组的情况下,是否有LINQ方法来创建对象数组?

时间:2010-01-21 21:37:22

标签: c# linq

举个例子,假设我有一个名字数组,我想通过调用一个带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世界太久了,我正试图在当前的停机时间进行现代化改造......

2 个答案:

答案 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);

然后,您将遍历列表以获取实例