Jeff
Jeff

Reputation: 21

How does FirstOrDefault evaluate an inner FirstOrDefault with a condition?

I have this issue where FirstOrDefault always returns the first item it encounters regardless of how the inner expression evaluated.

Lets say I have an array of companies.

Companies = {Company1, Company2, Company3}

.. and Each company contains an array of employee names.

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

Why do I always receive the first company with the following code?

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

Upvotes: 2

Views: 1657

Answers (1)

Matt Mitchell
Matt Mitchell

Reputation: 41823

I run this code:

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

And the result is:

String [] (2 items)  
  Employee3
  Employee4

Is your example not telling the whole story?

  • Does Company1 have Employee3 somewhere in their EmployeeList?
  • I see you are using LINQ-to-SQL, if this is correct, how do you have a property on a LINQ-to-SQL model that is a string array? Have you added an extension method / partial method to create this array?
  • Are the Employees not actually String (i.e. is the == overloaded or similar)

As a start, I'd recommend changing your code to use Any rather than FirstOrDefault != null

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

I also notice that you state:

FirstOrDefault always returns the first item it encounters regardless of how the inner expression evaluated

If this is the case, either you have overloaded FirstOrDefault in some way (unlikely) or your inner expression is always true for every example you've tried (i.e. in the example, the EmployeeList of your first Company has an element that == "Employee3" is true for).

Edit

Two great recommendations from comments:

  1. ingo suggets using list.Contains(item) rather than list.Any(el => el == item) which means using:

    var myCo = Companies.FirstOrDefault(c => c.EmployeeList.Contains("Employee3"));
    
  2. John L suggests that the items (Employee ?) in EmployeeList are value types or similar, such that default(Employee) is not null.

Upvotes: 6

Related Questions