Лямбда-выражения, как искать внутри объекта?
Вопрос
Я начинаю любить лямбда-выражения, но изо всех сил пытаюсь пройти эту стену:
public class CompanyWithEmployees {
public CompanyWithEmployees() { }
public Company CompanyInfo { get; set; }
public List<Person> Employees { get; set; }
}
Мой поиск:
List<CompanyWithEmployees> companiesWithEmployees = ws.GetCompaniesWithEmployees();
CompanyWithEmployees ces = companiesWithEmployees
.Find(x => x.Employees
.Find(y => y.PersonID == person.PersonID));
Итак, я хочу получить объект " CompanyWithEmployees " у меня есть тот Персона (Сотрудник), которого я ищу, но я получаю " Невозможно неявно преобразовать «Персона» в «bool») " что правильно, но если я не передаю объект Person, как может выполняться первый Find?
Решение
Поскольку вы хотите проверить наличие, попробуйте:
ces = companiesWithEmployees
.Find(x => x.Employees
.Find(y => y.ParID == person.ParID) != null);
Это проверит для любого Персона
с тем же ParID
; Если вы имеете в виду один и тот же экземпляр Person
(ссылка), тогда достаточно Contains
:
ces = companiesWithEmployees
.Find(x => x.Employees.Contains(person));
Другие советы
Find ()
возвращает найденный объект. Используйте Any ()
, чтобы просто проверить, является ли выражение истинным для любого элемента.
var ces = companiesWithEmployees
.Find(x => x.Employees
.Any(y => y.PersonID == person.PersonID));
ces = companiesWithEmployees
.First(x => x.Employees.Any(p=>p.PersonID == person.PersonID));
ces = companiesWithEmployees.Find( x => x.Employees.Find(...) );
.Find
возвращает только один объект, x.Employees.Find (..)
возвращает Person код>.
.Find
ожидает логический параметр (то есть результат условий), поэтому есть ошибка компилятора, которая говорит, что не может неявно преобразовать «Person» в «bool»
р>
.Where
может возвращать несколько объектов, поэтому может выполнять итерацию по всему списку .
используйте комбинацию .Where
и .Any
в вашем случае.
следующий код иллюстрирует разницу между .Where
, .Find
и .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; }
}
Это потому, что вы не указали правильное выражение Find для своего верхнего уровня Find.
Я покажу это здесь:
ces = companiesWithEmployees
.Find (x => x.Employees.Find(y => y.ParID == Person.ParID) /*condition is missing here*/);
Итак, каково условие для вашей начальной находки?
Самый простой будет
ces = companiesWithEmployees.FirstOrDefault(x =>
x.Employees.Any(y => y.PersonID == person.ParID));
без проверки на ноль