Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safely dereferencing FirstOrDefault call in Linq c#

Tags:

syntax

c#

linq

For brevity's sake in my code, i'd like to be able to do the following: having a collection, find the first element matching a lambda expression; if it exists, return the value of a property or function. If it doesn't exist, return null.

Updated examples w. classes

Let's have a collection of stuff

class Stuff
{
    public int Id { get; set; }
    public string Value { get; set; }
    public DateTime? ExecutionTime { get; set; }
}

What I am aiming for is a way to return nicely when calling this

var list = new Stuff[] { new Stuff() { Id = 1, Value = "label", ExecutionTime = DateTime.Now } };

// would return the value of ExecutionTime for the element in the list
var ExistingTime = list.FirstOrDefault(s => s.Value.Contains("ab")).ExecutionTime;

// would return null
var NotExistingTime = list.FirstOrDefault(s => s.Value.Contains("zzz")).ExecutionTime; 

Is it possible with some linq-syntax-fu or do I have to check explicitly for the return value before proceeding?

Original example w. strings

var stuff = {"I", "am", "many", "strings", "obviously"};

// would return "OBVIOUSLY"
var UpperValueOfAString = stuff.FirstOrDefault(s => s.contains("bvi")).ToUpper();

// would return null
var UpperValueOfAStringWannabe = stuff.FirstOrDefault(s => s.contains("unknown token")).ToUpper();

Comment: I shouldn't have used strings in my original example, since it slightly skews the question by centering it on the ToUpper method and the string class. Please consider the updated example

like image 647
samy Avatar asked Jun 27 '12 09:06

samy


People also ask

Which is better SingleOrDefault or FirstOrDefault?

When you want a default value is returned if the result set contains no record, use SingleOrDefault. When you always want one record no matter what the result set contains, use First or FirstOrDefault. When you want a default value if the result set contains no record, use FirstOrDefault.

What is the difference between first () and FirstOrDefault () Select methods in Linq?

The major difference between First and FirstOrDefault is that First() will throw an exception if there is no result data for the supplied criteria whereas FirstOrDefault() will return the default value (null) if there is no result data.

What is FirstOrDefault in Linq C#?

FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource) Returns the first element of the sequence that satisfies a condition, or a specified default value if no such element is found.

What is the use of FirstOrDefault in Linq?

Use the FirstorDefault() method to return the first element of a sequence or a default value if element isn't there. List<double> val = new List<double> { }; Now, we cannot display the first element, since it is an empty collection.


2 Answers

Why not just do:

stuff.Where(s => s.contains("bvi"))
     .Select(s => s.ToUpper())
     .FirstOrDefault()

If you have a "non-default default", you can do:

stuff.Where(s => s.contains("bvi"))
     .Select(s => s.ToUpper())
     .DefaultIfEmpty("Something Else")
     .First()
like image 132
Ani Avatar answered Oct 14 '22 11:10

Ani


I like this as an extension method:

public static U SelectMaybe<T, U>(this T input, Func<T,U> func)
{
    if (input != null) return func(input);
    else return default(U);
}

And usage:

var UpperValueOfAString = stuff.FirstOrDefault(s => s.Contains("bvi")).SelectMaybe(x => x.ToUpper());
var UpperValueOfAStringWannabe = stuff.FirstOrDefault(s => s.Contains("unknown token")).SelectMaybe(x => x.ToUpper());

This will chain return the default value (null in this case, but as is correct for that type), or call the relevant function and return that.

like image 45
yamen Avatar answered Oct 14 '22 10:10

yamen