Whilst writing unit tests for the standard query operators I paid particular attention to how the operators handled special cases of null, containing nulls and empty sets. Most results were as expected and detailed in the table below.
| Sum |
|
|
|
|
|
|
|
|
| |
int |
int? |
long |
long? |
double |
double? |
decimal |
decimal? |
| null source |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
| empty source |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
| source with >0 nulls |
N/A |
null values ignored |
N/A |
null values ignored |
N/A |
null values ignored |
N/A |
null values ignored |
| source has ALL nulls |
N/A |
0 |
N/A |
0 |
N/A |
0 |
N/A |
0 |
| positive overflow |
OverflowException |
OverflowException |
OverflowException |
OverflowException |
double.PositiveInfinity |
double.PositiveInfinity |
OverflowException |
OverflowException |
| negative overflow |
OverflowException |
OverflowException |
OverflowException |
OverflowException |
double.NegativeInfinity |
double.NegativeInfinity |
OverflowException |
OverflowException |
| |
| Min |
|
| |
int |
int? |
long |
long? |
double |
double? |
decimal |
decimal? |
| null source |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
| empty source |
InvalidOperationException |
null |
InvalidOperationException |
null |
InvalidOperationException |
null |
InvalidOperationException |
null |
| source with >0 nulls |
N/A |
null values ignored |
N/A |
null values ignored |
N/A |
null values ignored |
N/A |
null values ignored |
| source has ALL nulls |
N/A |
null |
N/A |
null |
N/A |
null |
N/A |
null |
| |
| Max |
|
| |
int |
int? |
long |
long? |
double |
double? |
decimal |
decimal? |
| null source |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
ArgumentNullException |
| empty source |
InvalidOperationException |
null |
InvalidOperationException |
null |
InvalidOperationException |
null |
InvalidOperationException |
null |
| source with >0 nulls |
N/A |
null values ignored |
N/A |
null values ignored |
N/A |
null values ignored |
N/A |
null values ignored |
| source has ALL nulls |
N/A |
null |
N/A |
null |
N/A |
null |
N/A |
null |
The situations I think might cause some issues are marked in red. My feelings are that inline aggregate extension methods should give the user the ability to specify a default value rather than throwing an exception that can only be handled by wrapping the entire LINQ over Object expression in a try/catch.
I would like to see some additional operators that will return the default value rather than an exception:
- MinOrDefault
- MaxOrDefault
- SumOrDefault