When I do a sum operation on some objects I have, they don’t return the expected result and instead miss the last item in the list.
Here’s the models used:
public class Item
{
public decimal Price { get; set; }
public List<ItemOption> Options { get; set; }
}
public class ItemOption
{
public decimal? Price { get; set; }
}
So when I do a sum operation like so it gives incorrect results, missing the last item…
items.Sum(x => x.Price + x.Options?.Sum(c => c.Price) ?? 0);
But when I do it with brackets like this, it works…
Console.WriteLine(items.Sum(x => x.Price + (x.Options?.Sum(c => c.Price) ?? 0)));
Any idea why adding brackets here would make it work as expected?
Here’s something I’ve tried, first write line returns £16.80 and 2nd write line returns £10.20
var items = new List<Item>
{
new Item
{
Price = 4.20M,
Options = new List<ItemOption>
{
new ItemOption
{
Price = null
}
}
},
new Item
{
Price = 6.00M,
Options = new List<ItemOption>
{
new ItemOption
{
Price = null
}
}
},
new Item
{
Price = 1.30M
},
new Item
{
Price = 5.30M
}
};
Console.WriteLine(items.Sum(x => x.Price + (x.Options?.Sum(c =>
c.Price) ?? 0)));
Console.WriteLine(items.Sum(x => x.Price + x.Options?.Sum(c =>
c.Price) ?? 0));
>Solution :
This happens due to C# operator precedence, addition has higher precedence then null-coalescing operator, so in the first case if x.Options is null x.Price + x.Options?.Sum(c => c.Price) ?? 0 is evaluated as:
(x.Price + (decimal?)null) ?? 0
Which is evaluated as:
null ?? 0
Due to lifted operators rules:
The predefined unary and binary operators or any overloaded operators that are supported by a value type
Tare also supported by the corresponding nullable value typeT?. These operators, also known as lifted operators, produce null if one or both operands are null; otherwise, the operator uses the contained values of its operands to calculate the result. For example:
int? a = 10;
int? b = null;
int? c = 10;
a++; // a is 11
a = a * c; // a is 110
a = a + b; // a is null