26

My real application issue looks exactly like below

Employee empl = new Employee(397947, "David", "Redson", 80000);
        employees.Add(empl);
        employees.Add(new Employee(174966, "Alfred", "Swanson", 50000));
        employees.Add(new Employee(848024, "Alima", "Bieyrou", 40000));
        employees.Add(new Employee(number: 397462, fName: "Robert",
                                     lName: "Nants", salary: 30000));


string s = employees.Where(a => a.EmployeeNumber == 20000).FirstOrDefault().FirstName;

As I am using FirstOrDefault, it is throwing error when there is no matching record. If there is a matching record, I want to return the value, or else it can be null or empty..

Selim Yildiz
  • 4,224
  • 6
  • 14
  • 25
python
  • 307
  • 1
  • 3
  • 7

9 Answers9

47

Select the string in your linq statement before your FirstOrDefault and you get your string or the default string:

string s = employees
    .Where(a => a.EmployeeNumber == 2000)
    .Select(a => a.FirstName)
    .FirstOrDefault();

This has the advantage that only the value that you will be using will be fetched, not the complete Employee.

Harald Coppoolse
  • 24,051
  • 6
  • 48
  • 92
  • 8
    Hmm, I'm wondering why this most natural solution is totally ignored. +1 – Ivan Stoev Jul 21 '16 at 09:51
  • Putting the FirstOrDefault at the end will often mean that the entire result is loaded into memory before the first element is selected. Replacing the Where with the FirstOrDefault will cause the underlying query to implement the selection as a Top 1. This boils down to differences in the implementation of the underlying LINQ provider. – Nick Harrison Apr 24 '18 at 22:17
  • 1
    I don't agree. FirstOrDefault does not load the entire collection. According to the reference source. It gets the enumerator, does ONE MoveNext and returns the Current. See https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs – Harald Coppoolse Apr 25 '18 at 06:31
  • For IQueryable it depends on the class that holds `Queryable.Expression`. Entity Framework DbSet class makes it a SQL "Select Top 1 ..." So also for IQueryable I don't see any evidence that the complete collection is downloaded. – Harald Coppoolse Apr 25 '18 at 06:37
  • 4
    This should be the accepted answer, more clear, shorter, and less data transferred in the majority case. – Scott Gartner May 30 '18 at 20:20
  • @HaraldCoppoolse Amazing. – H4ze Jan 20 '21 at 16:07
44

You need not to use Where and the FirstOrDefault in this case, you can specify the filter condition inside the FirstOrDefault itself. But which will give you null if there are no records satisfying the condition(because in the absence of first value it will give you the default value, for reference type objects the default value is null), you you should check for null before accessing the value, which will throws NullReferenceException. So Use like this:

var Employee=employees.FirstOrDefault(a => a.EmployeeNumber == 20000);
if(Employee!=null)
{
  string employee_name=Employee.FirstName;
  // code here
}

Or else you can use ?. to check for null like this:

string employee_name = employees.FirstOrDefault(a => a.EmployeeNumber == 20000)?.FirstName;
sujith karivelil
  • 26,861
  • 6
  • 46
  • 76
  • 1
    This method is not efficient. FirstOrDefault retrieves the complete Employee to local after which you throw away most fields. Use your SQL server profiler to check the SQL statement. – Harald Coppoolse Jul 21 '16 at 10:19
  • 1
    The null-propagating operator `?.` (aka Elvis operator) is not allowed in a queryable (LINQ-to-SQL or LINQ-to-Entities) collection. However, it works fine for a LINQ-to-Objects collection. – Suncat2000 Aug 29 '19 at 20:12
6

May be you can try using null propagation to make it easier:

string s = employees.Where(a => a.EmployeeNumber == 20000).FirstOrDefault()?.FirstName;
Ash
  • 2,425
  • 2
  • 17
  • 26
  • 3
    worth to mention that the null propagation operator only works in C# 6+ – fubo Jul 21 '16 at 05:50
  • 3
    @fubo C#6 is the **current** version of C#, I don't see why we need to mention that. We don't do that for other C# versions. – Ivan Stoev Jul 21 '16 at 09:48
  • As I commented earlier, this is not allowed in a queryable (LINQ-to-SQL or LINQ-to-Entities) collection because the operator is not translated. @Ivan Stoev We do mention C# versions in other answers where a behavior is not implemented in earlier versions. It's usually mentioned where only some versions support the operation being discussed. – Suncat2000 Aug 29 '19 at 20:20
4

You can use DefaultIfEmpty. Consider the following example:

var entries = new Employee[0];
var result = entries.DefaultIfEmpty(new Employee() { FirstName = "<default name>" }).First().FirstName;
grek40
  • 12,159
  • 1
  • 18
  • 46
2

If you are sure you've only one record for a given EmployeeNumber you could use SingleOrDefault extension.

var item = employees.SingleOrDefault(a => a.EmployeeNumber == 20000);
string s = "";

if(item!= null)
{
    s = item.FirstName;
    // your logic ... 
}

In case if you have multiple records for given employeenumber, use FirstOrDefault but do null check before accessing properties.

var item = employees.FirstOrDefault(a => a.EmployeeNumber == 20000);

string s = "";    
if(item!= null)
{
    s = item.FirstName;
    // your logic ... 
}
Hari Prasad
  • 15,659
  • 4
  • 18
  • 33
1

you can do like below

var employee = employees.FirstOrDefault(a => a.EmployeeNumber == 20000);
return employee != null ? employee.Name : string.Empty;
harishr
  • 16,726
  • 7
  • 70
  • 114
0

Assign value after checking if the object is null.

var emp = employees.Where(a => a.EmployeeNumber == 20000).FirstOrDefault();

string s = emp == null ? string.Empty: emp.FirstName;
fubo
  • 39,783
  • 16
  • 92
  • 127
Vivek.Shr
  • 1
  • 1
  • 1
  • 2
    What is the need for `Where`, you can specify the condition inside the `FirstOrDefault` – sujith karivelil Jul 21 '16 at 05:44
  • instead of var can use like the below if (employees.Where(a => a.EmployeeNumber == 397947).FirstOrDefault() != null) { string s = employees.Where(a => a.EmployeeNumber == 397947).FirstOrDefault().FirstName; } – python Jul 21 '16 at 05:47
  • @python : why would you execute the same expression two times just for checking null condition? It's better to store the result in a variable and then check the value of the variable. DRY principle- Don't Repeat Yourself. – Vivek.Shr Jul 22 '16 at 07:47
0
string employee_name = employees.FirstOrDefault(a => a.EmployeeNumber == 20000)??new Employee();

We can use this and avoid null exceptions occurring when and object is not created.

Shree
  • 18,997
  • 28
  • 86
  • 133
0

In C# 8 and later use the null-coalescing operator ?? and null checking operator ?.

Like this:

string s = employees?.Where(a => a.EmployeeNumber == 20000)
                     .FirstOrDefault()?
                     .FirstName ?? string.Empty;

To avoid any null exceptions in the employees list and any employee properties.

Hasan Fathi
  • 4,048
  • 4
  • 32
  • 45