tags:

views:

582

answers:

6

I'm starting to love Lambda expressions but I'm struggling to pass this wall:

public class CompanyWithEmployees
{
    public CompanyWithEmployees() { }
    public Company CompanyInfo { get; set; }
    public List<Person> Employees { get; set; }
}

My search:

List<CompanyWithEmployees> companiesWithEmployees = ws.GetCompaniesWithEmployees();
CompanyWithEmployees ces;

ces = companiesWithEmployees
    .Find(x => x.Employees
        .Find(y => y.PersonID == person.PersonID));

So, I want to get the Object "CompanyWithEmployees" that have that Person (Employee) that I'm looking for, but I'm getting "Cannot implicit convert 'Person' To 'bool')" witch is right, but if I'm not passing the Person object, how can the first Find executes?

Thanks.

+6  A: 

Because you want to check for existance, perhaps try:

    ces = companiesWithEmployees
        .Find(x => x.Employees
            .Find(y => y.ParID == person.ParID) != null);

This will check for any Person with the same ParID; if you mean the same Person instance (reference), then Contains should suffice:

    ces = companiesWithEmployees
        .Find(x => x.Employees.Contains(person));
Marc Gravell
The property was `ParID` when I posted ;-p
Marc Gravell
Yes it was, I had to changed it cause it's an internal name, so I changed to a public name :) I'm sorry for that, but I get the point :)
balexandre
I should note that by using just `Find`, you retain the ability to use 2.0 if you need; `Any`, `First`, etc require 3.5 - which is great if you have it ;-p
Marc Gravell
I ended up using .Contains, thank you Marc.Isn't Lambda Expression a treat or what? :-D
balexandre
I'm using get; set; a lot ... so I need 3.x ;)
balexandre
@balexandre - that (get;set;) is C# 3.0, which is a separate concept to the .NET version; you can use C# 3.0 even with .NET 2.0 (via multi-targetting).
Marc Gravell
@balexandre: get; set; will still work in 2.0. The compiler still generates 2.0 valid IL.
Ray Booysen
+2  A: 
ces = companiesWithEmployees
               .First(x => x.Employees.Any(p=>p.PersonID == person.PersonID));
Mehrdad Afshari
something as David :) you were late, no upvote for you ;-) but thank you anyway for you kindness and help.
balexandre
Actually, I was faster than David, you can check it by sorting the result by oldest first ;)
Mehrdad Afshari
A: 

That's because you haven't specified a legitimate Find expression for your top level Find.

I'll show it here:

ces = companiesWithEmployees
    .Find (x => x.Employees.Find(y => y.ParID == Person.ParID) /*condition is missing here*/);

So what is the condition for your initial find?

Jon Limjap
+6  A: 

Find() returns the found object. Use Any() to just check whether the expression is true for any element.

var ces = companiesWithEmployees
    .Find(x => x.Employees
        .Any(y => y.PersonID == person.PersonID));
David Schmitt
for all about .Any :D Thank you very much to remind me
balexandre
+1  A: 

ces = companiesWithEmployees.Find( x => x.Employees.Find(...) );

.Find returns only one object, x.Employees.Find(..) returns Person.

.Find expects boolean parameter(i.e. the result of conditions). that's why there's a compiler error that says Cannot implicit convert 'Person' To 'bool'.

.Where can return multiple objects, hence can iterate through all list.

use a combination of Where and Any in your case.

the following code will illustrate the difference between .Where .Find and .Any:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();


        var companiesWithEmployees = new List<CompanyWithEmployees>()
        {                
            new CompanyWithEmployees
            {                 
                CompanyInfo = new Company { CompanyName = "Buen" },
                Employees = new List<Person>() 
                { 
                    new Person { PersonID = 1976, PersonName = "Michael" },
                    new Person { PersonID = 1982, PersonName = "Mark" },
                    new Person { PersonID = 1985, PersonName = "Matthew" },                            
                    new Person { PersonID = 1988, PersonName = "Morris" }
                }
            },


            new CompanyWithEmployees
            {
                CompanyInfo = new Company { CompanyName = "Muhlach" },
                Employees = new List<Person>()
                {
                    new Person { PersonID = 1969, PersonName = "Aga" },
                    new Person { PersonID = 1971, PersonName = "Nino" },
                    new Person { PersonID = 1996, PersonName = "Mark" }
                }
            },

            new CompanyWithEmployees
            {
                CompanyInfo = new Company { CompanyName = "Eigenmann" },
                Employees = new List<Person>()
                {
                    new Person { PersonID = 1956, PersonName = "Michael" },                        
                    new Person { PersonID = 1999, PersonName = "Gabby" }
                }


            }
        };



        // just explicitly declared the types (instead of var) so the intent is more obvious

        IEnumerable<CompanyWithEmployees> whereAreMichaels = 
              companiesWithEmployees.Where(cx => cx.Employees.Any(px => px.PersonName == "Michael"));

        string michaelsCompanies = 
              string.Join(", ", whereAreMichaels.Select(cx => cx.CompanyInfo.CompanyName).ToArray());

        MessageBox.Show("Company(s) with employee Michael : " + michaelsCompanies);





        Person findAga = companiesWithEmployees
                              .Find(company => company.CompanyInfo.CompanyName == "Muhlach")
                              .Employees.Find(person => person.PersonName == "Aga");

        if (findAga != null)
            MessageBox.Show("Aga's ID : " + findAga.PersonID.ToString());


    }
}


class CompanyWithEmployees
{ 
    public Company CompanyInfo { get; set; }
    public List<Person> Employees { get; set; }
}

class Company
{
    public string CompanyName { get; set; }
}

class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}
Michael Buen
thank you so much for the explanation :) It was easy to follow.
balexandre
A: 

The easiest one would be

   ces = companiesWithEmployees.FirstOrDefault(x => x.Employees.Any(y => y.PersonID == person.ParID) );

without any null check

Dincer Uyav