Daily Knowledge Drop
A number of enhancements have been made to LINQ as part of .NET6 - one of those is the ability to set a default value to be returned from .FirstOrDefault()
.
Examples
List<> is being used in the below examples, but the method is available on all compatible types, not just List<>.
Simple type list
// list of 11 integers
var intValues = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Returns the first value greater than 4.
// A value from the list will be returned
Console.WriteLine(intValues.FirstOrDefault(i => i > 4));
// Returns the first value greater than 20.
// No qualifying value exists in the list,
// so the default value of type int will be returned (0 in this case)
Console.WriteLine(intValues.FirstOrDefault(i => i > 20));
// Returns the first value greater than 20. No qualifying value
// exists in the list, and as the new method override is being used,
// the explicitly supplied default value will be returned (-1 in this case)
Console.WriteLine(intValues.FirstOrDefault(i => i > 20, -1));
The output:
5
0
-1
Complex type list
The same process can be applied to more complex type. The below example uses a Person record (but the same would apply to a traditional class as well)
var personValues = new List<Person> {
new Person("Dave",30),
new Person("Nate",45),
new Person("Pat",60),
new Person("Taylor",25),
new Person("Chris",39)
};
// Returns the first Person with age of 30. A value from the list will be returned
Console.WriteLine(personValues.FirstOrDefault(p => p.Age == 30));
// Returns the first Person whose name starts with "J".
// No qualifying value exists in the list, so the default value of
// Person will be returned (null in this case)
Console.WriteLine(personValues.FirstOrDefault(p => p.Name.StartsWith("J")));
// Returns the first _Person_ whose name starts with "J".
// No qualifying value exists in the list, and as the new method override
// is being used, the explicitly supplied default value will be returned
// (Person initialized with "John Doe" and 0 in this case)
Console.WriteLine(personValues.FirstOrDefault(p => p.Name.StartsWith("J"),
new Person("John Doe", 0)));
public record Person(string Name, int Age);
The output. The blank line indicates the null record returned from the 2nd call to FirstOrDefault():
Person { Name = Dave, Age = 30 }
Person { Name = John Doe, Age = 0 }
Empty list
This method can also be used to return a specific default value in the case of an empty list.
var stringValues = new List<string>();
// Returns the first value in the list.
// The list is empty, so the default value of string
// will be returned (empty string in this case)
Console.WriteLine(stringValues.FirstOrDefault());
// Returns the first value in the list.
// The list is empty, and as the new method override is
// being used, the explicitly supplied default value
// will be returned ("empty" in this case)
Console.WriteLine(stringValues.FirstOrDefault("empty"));
The output is as follows, the blank line indicating the empty string returned from the 1st call to FirstOrDefault():
empty
Conclusion
A small, simple update made to LINQ, but nevertheless a very useful feature which I'm sure will get a fair amount of usage.
Daily Drop 19: 25-02-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.