Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FirstOrDefault: Default value other than null

Tags:

.net

linq

As I understand it, in Linq the method FirstOrDefault() can return a Default value of something other than null.

No. Or rather, it always returns the default value for the element type... which is either a null reference, the null value of a nullable value type, or the natural "all zeroes" value for a non-nullable value type.

Is there any particular way that this can be set up so that if there is no value for a particular query some predefined value is returned as the default value?

For reference types, you can just use:

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

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


You can use DefaultIfEmpty followed by First:

T customDefault = ...;
IEnumerable<T> mySequence = ...;
mySequence.DefaultIfEmpty(customDefault).First();

General case, 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 can't really tell if there was anything in your sequence, or if the first value was the default.

If you care about this, you could 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 could be done just as well by .DefaultIfEmpty(...).First().


From the documentation for FirstOrDefault

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

From the documentation for default(T):

the default keyword, which will return null for reference types and zero for numeric value types. For structs, it will return each member of the struct initialized to zero or null depending on whether they are value or reference types. For nullable value types, default returns a System.Nullable, which is initialized like any struct.

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