2010-01-21 8 views
20

उदाहरण के तौर पर, कहें कि मेरे पास नामों की एक सरणी है और मैं string name लेता है जो एक कन्स्ट्रक्टर को कॉल करके Person ऑब्जेक्ट्स की एक सरणी बनाना चाहता हूं।सी #: क्या कन्स्ट्रक्टर पैरामीटर की सरणी दी गई वस्तुओं की सरणी बनाने के लिए कोई 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(); 
} 

मैं बहुत लंबा अब के लिए नेट 2.0 दुनिया में फंस रहे हैं और मैं अपने वर्तमान से अन्तराल में आधुनिक बनाने के लिए कोशिश कर रहा हूँ ...

उत्तर

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

स्पष्टीकरण:

Enumerable.Select प्रक्षेपण के लिए LINQ विधि है। यही है, Foo एस का अनुक्रम लेना और उन्हें Bar एस पर कुछ नियम Func<Foo, Bar> के माध्यम से पेश करना जो Foo एस खाता है और Bar s निकालता है। इस प्रकार

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

प्रकार IEnumerable<Person> के अनुक्रम के लिए प्रकार IEnumerable<string> के अनुक्रम names का अनुमान है। यदि आप कार्यात्मक प्रोग्रामिंग जानते हैं तो यह map की भूमिका निभाता है।

अब, यहां एक सूक्ष्म बिंदु है जो समझने योग्य है; यह लगभग निश्चित रूप से LINQ के सबसे महत्वपूर्ण लेकिन आसानी से गलत समझा पहलुओं में से एक है। यह स्थगित निष्पादन की अवधारणा है। जब हम कहते हैं

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

यह वास्तव में प्रक्षेपण (यानी, वह अभी तक Person के उदाहरण निर्माता पैरामीटर के रूप में names में string रों का प्रयोग कर बनाया पैदा नहीं करता) प्रदर्शन नहीं करता। इसके बजाए, यह कुछ ऐसा बनाता है जो अनुक्रम 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) 

है में नहीं मिलता है। यह एक लैम्ब्डा अभिव्यक्ति है, और आप How does this LINQ Expression work? के उत्तर में उनके लिए एक परिचय प्राप्त कर सकते हैं।

+0

प्राप्त करने के लिए आप सूची के माध्यम से लूप करेंगे, अब मैं F # में 'map' की बजाय 'select' को देखकर उलझन में हूं। – ChaosPandion

+0

काफी आसान है! धन्यवाद!! –

+1

@ChosPandion: हाँ, मुझे यह जानना अच्छा लगेगा कि उदाहरण के लिए 'चयन' और' कुल 'के बजाय अधिक परिचित' मानचित्र 'और' गुना 'का उपयोग क्यों नहीं किया गया था। – jason

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

तो करना चाहते हैं उदाहरण

संबंधित मुद्दे