2010-01-21 33 views
20

Ví dụ, giả sử tôi có một mảng tên và tôi muốn tạo một mảng các đối tượng Person bằng cách gọi một hàm tạo có số string name.C#: Có cách nào LINQ để tạo một mảng các đối tượng được đưa ra một mảng các tham số của hàm tạo không?

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

tôi đã bị mắc kẹt trong thế giới Net 2.0 quá lâu nay và tôi đang cố gắng để hiện đại hóa trong thời gian chết hiện tại của tôi ...

Trả lời

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

Giải thích:

Enumerable.Select là phương pháp LINQ để chiếu. Tức là, lấy một dãy gồm Foo s và chiếu chúng theo số Bar s qua một số quy tắc Func<Foo, Bar> ăn Foo s và phun ra Bar s. Như vậy

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

là một phóng chiếu của chuỗi names loại IEnumerable<string> đến một chuỗi các loại IEnumerable<Person>. Nếu bạn biết lập trình hàm, nó sẽ đóng vai trò là map.

Bây giờ, có một điểm tinh tế ở đây đáng để hiểu; điều này gần như chắc chắn là một trong những khía cạnh quan trọng nhất nhưng dễ hiểu lầm của LINQ. Đây là khái niệm thực hiện trì hoãn. Khi chúng ta nói

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

điều này không thực sự thực hiện chiếu (ví dụ, nó chưa tạo ra các trường hợp Person xây dựng bằng cách sử dụng string s trong names như thông số nhà xây dựng). Thay vào đó, nó tạo ra một cái gì đó mà nắm bắt các quy tắc làm thế nào để dự án trình tự names thành một chuỗi các Person. Chỉ khi quy tắc đó (được gọi là một trình lặp) thực sự được thực hiện thì việc chiếu diễn ra.

Một cách để làm cho việc thực hiện này xảy ra là sử dụng phương thức Enumerable.ToArray, về cơ bản, nói lặp qua chuỗi và trả lại kết quả dưới dạng mảng.

Có nhiều cách khác để thực hiện việc thực hiện. Ví dụ

IEnumerable<Person> persons = names.Select(s => new Person(s)); 
foreach(Person p in persons) { 
    Console.WriteLine(p.Name); 
} 

hoặc

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

đó sẽ thực hiện "đầu tiên" chiếu (ví dụ: new Person(names[0])) và gán kết quả cho p.

Tất nhiên, điều này không còn nhận được vào chính xác những gì

s => new Person(s) 

là. Đó là một biểu thức lambda, và bạn có thể giới thiệu cho họ trong câu trả lời của tôi cho How does this LINQ Expression work?.

+0

Tôi bị nhầm lẫn khi thấy 'Chọn' thay vì' bản đồ' như trong F #. – ChaosPandion

+0

Đủ dễ dàng! Cảm ơn!! –

+1

@ChaosPandion: Vâng, tôi rất muốn biết tại sao 'map' và' fold' quen thuộc hơn không được sử dụng thay cho 'Select' và' Aggregate', chẳng hạn. – jason

1

Tôi đang đăng trường hợp này mà người khác cần ánh sáng trên một kịch bản hơi khác. Đây là trường hợp của tôi, và tôi đã sử dụng câu trả lời của Jason để đến đó.

Hãy tưởng tượng bạn có một lớp học với tên của người đó, và chức danh công việc, và bạn muốn để điền vào đó đối tượng:

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... 
} 

Sau đó, bạn sẽ làm

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

Sau đó, bạn sẽ lặp qua danh sách để nhận các trường hợp

Các vấn đề liên quan