selecting a property from FirstOrDefault in case FirstOrDefault returns null

前端 未结 1 1778
半阙折子戏
半阙折子戏 2020-12-04 01:57

I want to make following statement:

var block = blocksById.FirstOrDefault(X => X.Value == tracResult.ID).Key

My question is how to deal

相关标签:
1条回答
  • 2020-12-04 02:24

    Since the introduction of the null conditional operators (?), it's as simple as:

    var block = blocksById.FirstOrDefault(X => X.Value == tracResult.ID)?.Key;
    

    Keep in mind that in this scenario, even if Value is an int, block will be of type Nullable<int>, and hence, can be null.

    However if what you want to assign a default value if null is returned you can make use of null coalescing operator (??) is this way:

    var block = blocksById.FirstOrDefault(X => X.Value == tracResult.ID)?.Key ?? 6;
    

    Nevertheless, for more complex Select statements, the following is still valid...


    Some time ago...

    Split it in Where and Select:

    var block = blocksById.Where(x => x.Value == tracResult.ID)
                          .Select(x => x.Key)
                          .FirstOrDefault();
    

    That way you won't get a NullRefferenceException if the FirstOrDefault returns null.

    Alternative you can give it a default value like this:

    var block = blocksById.Where(x => x.Value == tracResult.ID)
                          .Select(x => x.Key)
                          .FirstOrDefault() ?? somedefaultvalue;
    

    Or as @Silvermind stated for non nullable to nullable types (int's):

    var block = blocksById.Where(x => x.Value == tracResult.ID)
                          .Select(x => (int?) x.Key)
                          .FirstOrDefault() ?? somedefaultvalue;
    

    Update: some people seems to have doubts about this being a valid use case and argue that the check for null has to be done later on in the program.

    While in a lot of circumstances this is the case, is doesn't always have to be true, or if it is, it might be more convenient this way.

    Some examples:

    //one liner, null check delegated (not my favorite): 
    return SomeCalculatedValue(collection.Where(condition).Select(selection).FirstOrDefault());
    
    //or a mapping (shown with default value):
    var result = collection.Where(condition)
                           .Select(c => 
                               { 
                                    Foo = c.Foo,
                                    Bar = c.Bar
                               }).FirstOrDefault()) ?? new { Foo = "New", Bar = "Empty"};
    
    0 讨论(0)
提交回复
热议问题