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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:36:20  来源:igfitidea点击:

C#: Is there a LINQ way to create an array of objects given an array of constructor parameters?

c#linq

提问by Austin Salonen

As an example, say I have an array of names and I want to create an array of Personobjects 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.Selectis the LINQ method for projection. That is, taking a sequence of Foos and projecting them to Bars via some rule Func<Foo, Bar>that eats Foos and spits out Bars. Thus

Enumerable.Select是用于投影的 LINQ 方法。也就是说,取一系列Foos 并Bar通过某种规则Func<Foo, Bar>将它们投影到s 中,该规则吃掉Foos 并吐出Bars。因此

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

is a projection of the sequence namesof 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 Personconstructed using the strings in namesas constructor parameters). Instead, it creates something that captures the rule of how to project the sequence namesinto a sequence of Person. It's only when that rule (known as an iterator) is actually executed does the projection take place.

这实际上并不执行投影(即,它尚未创建Person使用stringsnames作为构造函数参数的constructed实例)。相反,它创建了一些捕获如何将序列投影namesPerson. 只有在实际执行该规则(称为迭代器)时才会进行投影。

One way to cause this execution to occur is to use the method Enumerable.ToArraywhich 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

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