Ternary operator in Link
var result = from payroll in currentMonthPayroll
select new SalaryDifference
{
PreviousMonthSalary = previousMonthPayroll.Where(t => t.EmployeeId == payroll.EmployeeId).FirstOrDefault() == null ?
default(decimal) : previousMonthPayroll.Where(t => t.EmployeeId == payroll.EmployeeId).FirstOrDefault().Salary,
};
Is there a way to avoid repeating logic previousMonthPayroll.Where(t => t.EmployeeId == payroll.EmployeeId).FirstOrDefault()
to select a value Salary
?
I tried:
previousMonthPayroll.Where(t => t.EmployeeId == payroll.EmployeeId)
.FirstOrDefault().Salary ?? default(decimal);
But if previousMonthPayroll.Where(t => t.EmployeeId == payroll.EmployeeId).FirstOrDefault()
null, it throws an exception.
As you can see from all the answers, there are several ways to do this, my preferred way is:
var result = from payroll in currentMonthPayroll
select new SalaryDifference
{
PreviousMonthSalary = previousMonthPayroll
.Where(t => t.EmployeeId == payroll.EmployeeId)
.Select(prev => prev.Salary)
.FirstOrDefault()
};
you can use Enumerable.DefaultIfEmpty
previousMonthPayroll.Where(t => t.EmployeeId == payroll.EmployeeId)
.DefaultIfEmpty(yourDefaultObject)
.First();
Where yourDefaultObject
is the default salary object default(decimal)
.
You can use the keyword let
:
from payroll in currentMonthPayroll
let prevSalary = previousMonthPayroll.FirstOrDefault(t => t.EmployeeId == payroll.EmployeeId)
select new SalaryDifference
{
PreviousMonthSalary = prevSalary != null ? prevSalary.Salary : default(decimal)
};
See MSDN
If you're using C # 6.0, you can mix the safe navigation operator with the null coalescing operator:
PreviousMonthSalary = previousMonthPayroll
.Where(t => t.EmployeeId == payroll.EmployeeId).FirstOrDefault()?.Salary
?? default(decimal)
What you are doing is essentially concatenating with enumerable sequences, so why not say so and let LINQ take care of the details:
var result = from currentPayroll in currentMonthPayroll
join previousPayroll in previousMonthPayroll on currentPayroll.EmployeeId equals previousPayroll.EmployeeId
into joined
from r in joined.DefaultIfEmpty()
select new SalaryDifference
{
PreviousMonthSalary = r == null ? default(decimal) : r.Salary,
};
It will also be beneficial to be much more efficient than other approaches.