A fairly common interview question I have for any C#/.NET Developer revolves around the difference between First and FirstOrDefault LINQ statements. There’s a general flow to the questions that basically go something like :
What’s the difference between First and FirstOrDefault
When answered, I follow it up with :
So when FirstOrDefault can’t find a value, what does it return?
Commonly, I actually have people say things like it always returns null. Which is incorrect, it returns the “default” value for that type. Essentially, doing something like default(T). But if they get this part right, then I follow it up with things like
So what is the default value then? What would be the default value for a type of integer?
The correct answer to the above is 0. I’m not sure if it’s a difficult set of questions or not (Certainly many get it wrong), but it’s definitely something you will run into a lot in your career if you develop in C# for any length of time.
One of the main reasons I ask this question, is often I see code across all levels that works something like this :
var hayStack = new List { 1, 2, 2 };
var needle = 3;
var foundValue = hayStack.FirstOrDefault(x => x == needle);
if(foundValue == 0)
{
Console.WriteLine(“We couldn’t find the value”);
}
This works of course, but what if needle actually is the number 0? You have to do a bit of a dance to work out was it truly not found, or is the value you are looking for actually the default value anyway. You have a couple of options :
Run a LINQ Any statement beforehand to ensure that your list does indeed contain the item
Cast the list to a nullable variant of the type if not already, so you can ensure you get null back if not found
Use First instead of FirstOrDefault and catch the exception
You might think this is only really an issue in edge cases where you are using primitives that typically aren’t nullable, but with the introduction of Nullable Reference types in C# 8, this is actually going to become a very common scenario.
.NET 6 introduces the concept of being able to pass in what the default value should be, should the item not be found. So for example, this code is now valid in .NET 6.
var hayStack = new List<int?> { 1, 2, 2 };
var needle = 3;
var foundValue = hayStack.FirstOrDefault(x => x == needle, -1);
if(foundValue == -1)
{
Console.WriteLine(“We couldn’t find the value”);
}
But… Hold on. All we are doing here is saying instead of returning 0, return -1. Oof!
As it turns out, the IEnumerable method still must return a valid integer. And because our type is not nullable, even with this extension method, we can’t force it to return null. This goes for FirstOrDefault, SingleOrDefault and LastOrDefault.
The reason for this article I guess is to first and foremost to introduce the new extension, but also secondly to say, it doesn’t quite solve the problem that I thought it would at first look. You still must return a valid type. It doesn’t make it as useful as I first thought, but at the very least, it may help in some very edge scenarios, for example upserting values.
The post LINQ OrDefault Enhancements In .NET 6 appeared first on .NET Core Tutorials.