Как FirstOrDefault оценивает внутреннее FirstOrDefault с условием? - PullRequest
2 голосов
/ 05 мая 2011

У меня есть проблема, когда FirstOrDefault всегда возвращает первый элемент, с которым он сталкивается, независимо от того, как оценивалось внутреннее выражение.

Допустим, у меня есть множество компаний.

Companies = {Company1, Company2, Company3}

.. и каждая компания содержит массив имен сотрудников.

Company1.EmployeeList = {"Employee1", "Employee2"}
Company2.EmployeeList = {"Employee3", "Employee4"}
Company3.EmployeeList = {"Employee5", "Employee6"}

Почему я всегда получаю первую компанию со следующим кодом?

var myCompany = Companies.FirstOrDefault(c=> c.EmployeeList.FirstOrDefault(name => name == "Employee3") != null);

1 Ответ

6 голосов
/ 05 мая 2011

Я запускаю этот код:

string[] s1 = new [] {"Employee1", "Employee2"};
string[] s2 = new []  {"Employee3", "Employee4"};
string[] s3 = new []  {"Employee5", "Employee6"};
string[][] s = new [] { s1,s2,s3 };

var result = s.FirstOrDefault(c => c.FirstOrDefault(n => n == "Employee3") != null);

И результат:

String [] (2 items)  
  Employee3
  Employee4

Ваш пример не рассказывает всю историю?

  • Company1 есть Employee3 где-то в их EmployeeList?
  • Я вижу, что вы используете LINQ-to-SQL, если это правильно, как у вас есть свойство в модели LINQ-to-SQLэто массив строк?Вы добавили метод расширения / частичный метод для создания этого массива?
  • На самом деле Employees не String (т. Е. == перегружен или похож)

Для начала я бы рекомендовал изменить код для использования Any вместо FirstOrDefault != null

var myCompany = Companies
   .FirstOrDefault(c => c.EmployeeList.Any(name => name == "Employee3"));

Я также заметил, что вы заявляете:

FirstOrDefault всегда возвращаетпервый элемент, с которым он сталкивается, независимо от того, как оценивалось внутреннее выражение

Если это так, либо вы перегрузили FirstOrDefault каким-то образом (маловероятно), либо ваше внутреннее выражение всегда верно для каждого примерапробовал (т.е. в примере EmployeeList вашего первого Company имеет элемент, для которого == "Employee3" имеет значение true).

Edit

Две замечательные рекомендации из комментариев:

  1. Инго предлагает использовать list.Contains(item) вместо list.Any(el => el == item), что означает использование:

    var myCo = Companies.FirstOrDefault(c => c.EmployeeList.Contains("Employee3"));
    
  2. John Lпредполагает, что элементы (Employee?) в EmployeeList являются типами значений или аналогичными, так что default(Employee) не являетсят null.

...