Safely dereferencing FirstOrDefault call in Linq c#

后端 未结 3 1049
谎友^
谎友^ 2021-02-12 22:08

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 valu

相关标签:
3条回答
  • 2021-02-12 22:25

    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.

    0 讨论(0)
  • 2021-02-12 22:29

    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()
    
    0 讨论(0)
  • 2021-02-12 22:37

    Update:

    Based on the question clarification, you don't need any extra code to achieve what you want. Simply use a where clause and a select projection clause:

    var theString = stuff
        .Where(s => s.contains("unknown token"))
        .Select(s => s.ToUpper())
        .FirstOrDefault();
    


    Old Answer

    As suggested in the comments (and made generic in another answer), wrap the ToUpper call in an extension method. Extension methods boil down to syntax sugar around static method calls, so they can handle nulls just fine.

    static class StringExtensions
    {
        public static string PossiblyToUpper(this string s)
        {
            if (s != null)
                return s.ToUpper();
    
            return null;
        }
    }
    

    Your call would become:

    var upperValueOfAStringWannabe = stuff
        .FirstOrDefault(s => s.contains("unknown token"))
        .PossiblyToUpper();
    

    It is now just a discussion over whether the extension method to simply support single-line style code is more expressive than multiple lines - at the end of the day, expressing the intent of the code is more important than what the code looks like.

    Personally I think extension methods that handle nulls are confusing at first glance, as they are sugared up to look like regular methods.

    0 讨论(0)
提交回复
热议问题