I was trying to use Enumerable.SequenceEqual(x,y)
as I expected it to work based on
Object.Equals(x,y)
method, which returns false if x or y is null, and true if both are null (for null cases).
However Enumerable.SequenceEqual(x,y)
throws exception if any parameter is a null reference and will not return true if it is given two nulls.
In my code I check for collection equality quite often so I created a method that mimics Object.Equals
behaviour for sequences but I just wonder whats the logic behind such default behaviour, and is there maybe an existing method with no exceptions on nulls?
Well, the MSDN documentation explicitly states that it throws an ArgumentNullException
in case any one of the passed in sequences is null. I assume it's to keep consistency with "standard behaviour" where an object throws a NullReferenceException
when you try to dereference it. Consider this:
List<int> foo = null;
foo.SequenceEqual(new List<int>());
This would be ok as SequenceEqual
is an extension method and therefore can handle a null object but it would also be confusing. Every extension method provided by Linq follows this behaviour as far as I know. Also you don't need to handle special null cases for every extension method (you would need to agree about sensible behaviour and add additional logic and maintain and test it). Saying that it is illegal makes it more robust (against logic bugs) and consistent from a framework perspective. I use Linq a lot and never ran into that problem - I just make sure all my sequences are not null. Reduces code clutter a lot (removes lots of null checks from the code).
The point at which it is checking for sequence equality is not when that exception is being thrown. It is being thrown earlier as an argument validator. Consider the method:
public static bool SequenceEquals<T>(this IEnumerable<T> source, IEnumerable<T> target)
{
// Stuff
}
We explicitly need to check that source
and target
are not null, because if any of them are, then we can't check for sequence equality. This is an unworkable state, and the result of SequenceEquals
should be governed by the contents of the enumerables, not the state of the enumerables. If it were to include the latter, when returning false
, how would the caller know whether it is actually failing because the sequences are not equal, or whether one or both of the enumerables are null
?
If we didn't thrown an ArgumentNullException
here, the CLR would thrown a NullReferenceException
when you try and access one of the null
enumerables. Simply saying Object reference not set to an instance of an object
is a lot less helpful then The argument <something> cannot be null
.
Remember, the type of exception thrown is typically one of the most helpful indicators about why an exception was thrown.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With