Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
440 views
in Technique[技术] by (71.8m points)

c# - selecting a property from FirstOrDefault in case FirstOrDefault returns null

I want to make following statement:

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

My question is how to deal with it more correctly in case I have FirstOrDefault null value. I just not feel that if statments the only solution that can be here...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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"};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...