FirstOrDefault: non-zero default value

As I understand it, in Linq, the FirstOrDefault() method can return the Default value of something other than null. What I did not develop is that this method (and similar) can be returned to other than null when there are no elements in the query. Is there any special way that this can be configured so that if there is no value for a particular request, the value of a specific value is returned as the default value?

+86
linq
Oct 19 '12 at 10:25
source share
10 answers

The general case, and not just for value types:

 static class ExtensionsThatWillAppearOnEverything { public static T IfDefaultGiveMe<T>(this T value, T alternate) { if (value.Equals(default(T))) return alternate; return value; } } var result = query.FirstOrDefault().IfDefaultGiveMe(otherDefaultValue); 

Again, this cannot really tell if there was something in your sequence, or if the first value was the default.

If you're interested, you can do something like

 static class ExtensionsThatWillAppearOnIEnumerables { public static T FirstOr<T>(this IEnumerable<T> source, T alternate) { foreach(T t in source) return t; return alternate; } } 

and use as

 var result = query.FirstOr(otherDefaultValue); 

although, as Mr. Steak points out, this can also be done with .DefaultIfEmpty(...).First() .

+29
Oct 19 '12 at 10:34
source share

As I understand it, in Linq, the FirstOrDefault () method can return a default value other than zero.

No. Rather, it always returns the default value for the element type ... which is either a null reference, or a null value of the NULL value type, or a natural "all zeros" value for the value type that is not NULL.

Is there any specific way this can be configured so that if there is no value for a particular request, the value of a specific value is returned as the default value?

For reference types, you can simply use:

 var result = query.FirstOrDefault() ?? otherDefaultValue; 

Of course, this will also give you a "different default value" if the first value is present, but is a null reference ...

+129
Oct 19 '12 at 10:30
source share

You can use DefaultIfEmpty , and then First :

 T customDefault = ...; IEnumerable<T> mySequence = ...; mySequence.DefaultIfEmpty(customDefault).First(); 
+36
Jun 03 '14 at 7:34
source share

From the documentation for FirstOrDefault

[Returns] the default value (TSource) if the source is empty;

From the documentation for default (T) :

a default keyword that will return null for reference types and zero for numeric value types. For structs, it returns each member of the structure, initialized to zero or null, depending on whether they are values โ€‹โ€‹or reference types. For value types with a null value, System.Nullable returns by default, which is initialized like any structure.

Therefore, the default value can be zero or 0 depending on whether the type is a reference or a value type, but you cannot control the default behavior.

+14
Oct 19 '12 at 10:33
source share

Copied from @sloth comment

Instead of YourCollection.FirstOrDefault() you can use YourCollection.DefaultIfEmpty(YourDefault).First() , for example.

Example:

 var viewModel = new CustomerDetailsViewModel { MainResidenceAddressSection = (MainResidenceAddressSection)addresses.DefaultIfEmpty(new MainResidenceAddressSection()).FirstOrDefault( o => o is MainResidenceAddressSection), RiskAddressSection = addresses.DefaultIfEmpty(new RiskAddressSection()).FirstOrDefault(o => !(o is MainResidenceAddressSection)), }; 
+6
Jan 16 '15 at 10:51
source share

You can also do it

  Band[] objects = { new Band { Name = "Iron Maiden" } }; first = objects.Where(o => o.Name == "Slayer") .DefaultIfEmpty(new Band { Name = "Black Sabbath" }) .FirstOrDefault(); // returns "Black Sabbath" 

Only linq is used here - yipee!

+4
Jan 02 '15 at 20:02
source share

In fact, I use two approaches to avoid a NullReferenceException when I work with collections:

 public class Foo { public string Bar{get; set;} } void Main() { var list = new List<Foo>(); //before C# 6.0 string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar; //C# 6.0 or later var barCSharp6 = list.FirstOrDefault()?.Bar; } 

For C # 6.0 or later:

Use ?. or ?[ to check if the value is null before accessing the membership Documentation of Null-conditional statements

Example: var barCSharp6 = list.FirstOrDefault()?.Bar;

Old C # version:

Use DefaultIfEmpty() to get the default value if the sequence is empty. MSDN Documentation

Example: string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;

+2
May 09 '17 at 19:11
source share

I had a similar situation, and I was looking for a solution that allows me to return an alternate default value without worrying about it from the caller every time I need it. What we usually do if Linq does not support what we want is to write a new extension that will take care of this. This is what I did. Here is what I came up with (not tested):

 public static class EnumerableExtensions { public static T FirstOrDefault<T>(this IEnumerable<T> items, T defaultValue) { foreach (var item in items) { return item; } return defaultValue; } public static T FirstOrDefault<T>(this IEnumerable<T> items, Func<T, bool> predicate, T defaultValue) { return items.Where(predicate).FirstOrDefault(defaultValue); } public static T LastOrDefault<T>(this IEnumerable<T> items, T defaultValue) { return items.Reverse().FirstOrDefault(defaultValue); } public static T LastOrDefault<T>(this IEnumerable<T> items, Func<T, bool> predicate, T defaultValue) { return items.Where(predicate).LastOrDefault(defaultValue); } } 
+1
Aug 11 '17 at 7:39 on
source share

Instead of YourCollection.FirstOrDefault() you can use YourCollection.DefaultIfEmpty(YourDefault).First() , for example.

-2
Apr 6 '17 at 8:53 on
source share

Use DefaultIfEmpty() instead of FirstOrDefault() .

-3
Jun 16 '16 at 10:04 on
source share



All Articles