2010-01-21 67 views
20

作爲一個例子,說我有一個名稱數組,我想通過調用一個構造函數來創建一個Person對象的數組,這個構造函數需要string nameC#:有沒有一種LINQ方法來創建給定的構造函數參數數組的對象數組?

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的世界太久,現在,我想在我目前的停機時間現代化...

回答

53
// names is string[] 
Person[] people = names.Select(s => new Person(s)).ToArray(); 

說明:

Enumerable.Select是投影的LINQ方法。也就是說,通過一系列Foo s並通過一些規則Func<Foo, Bar>將它們投射到Bars,該規則吃到Foos並且吐出Bars。因此

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

IEnumerable<string>是類型的序列namesIEnumerable<Person>類型的序列的投影。如果你知道函數編程,它扮演着map的角色。

現在,這裏有一個微妙的觀點值得理解;這幾乎肯定是LINQ最重要但容易被誤解的方面之一。這是延期執行的概念。當我們說

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

這實際上並不執行投影(即,它尚未創建names作爲構造函數的參數使用string大廈造價的的Person實例)。相反,它會創建一些內容,以捕獲如何將序列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?的回答中得到他們的介紹。

+0

我現在看到'Select'而不是'map'像F#一樣困惑。 – ChaosPandion

+0

夠簡單!謝謝!! –

+1

@ChaosPandion:是的,我想知道爲什麼沒有使用比較熟悉的'map'和'fol​​d'而不是'Select'和'Aggregate'。 – jason

1

我發佈這個incase其他人需要一個稍微不同的情況下光。這是我的情況,我用傑森的答案來到那裏。

想象一下,你有這個人的名字一個類,職務和要填充該對象:

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

然後你會通過列表循環獲取實例

相關問題