hatchetaxesaw
hatchetaxesaw

Reputation: 183

What is proper way to write this linq lambda expression and deal with nulls?

While this works, I'm fairly certain that there is a more concise (and proper?) way to write this expression.

    double currentPopulation = 0.0;
    if (detailmetrics.FirstOrDefault(dm => dm.MetricScopeID == 2 && dm.MetricTypeID == 1 &&
                                           dm.Timeframe.Equals("C")) != null)
    {
         currentPopulation = Convert.ToDouble(
             detailmetrics.FirstOrDefault(dm => dm.MetricScopeID == 2 && dm.MetricTypeID == 1 &&
                                          dm.Timeframe.Equals("C")
             ).MetricValue
         );
    }

Upvotes: 0

Views: 320

Answers (4)

DotNet Developer
DotNet Developer

Reputation: 3018

Simply

double currentPopulation = detailmetrics
    .Where(dm => dm.MetricScopeID == 2 && dm.MetricTypeID == 1 && dm.Timeframe.Equals("C"))
    .Select(a => Convert.ToDouble(a.MetricValue))
    .FirstOrDefault();

Upvotes: 5

to StackOverflow
to StackOverflow

Reputation: 124696

Lots of ways to skin a cat, including (your predicate omitted for brevity):

currentPopulation = Convert.ToDouble(
    detailmetrics.FirstOrDefault(predicate)?.MetricValue ?? "0"
    );

The above assumes the MetricValue is a string that is either null or a valid double, and that you want a 0 result if it is null.

If you don't want to make that assumption, you could write your own "safe" conversion method that handles nulls and invalid values, e.g.:

currentPopulation = 
    SafeConvert(detailmetrics.FirstOrDefault(predicate)?.MetricValue);

public double? SafeConvert(string value)
{
    ... your implementation e.g. ...
    if (String.IsNullOrEmpty(value)) return null;
    if (Double.TryParse(value, ... out double result)) return result; 
    ... handle invalid double values ...
}

Upvotes: 0

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112342

Assign the query result to a temporary variable to avoid evaluating it twice.

var dm = detailmetrics.FirstOrDefault(
    dm => dm.MetricScopeID == 2 && dm.MetricTypeID == 1 && dm.Timeframe.Equals("C")
);
if (dm != null) {
    currentPopulation = Convert.ToDouble(dm.MetricValue);
} else {
    currentPopulation = 0.0;
}

I don't know the type of MetricValue. If it is a string for example, you could write it shorter with (instead of the if-statement):

currentPopulation = Convert.ToDouble(dm?.MetricValue ?? "0");

This means: if dm is null, take "0" (because the expression to the left of ?? yields null), otherwise take dm.MetricValue and then convert to double.

See also:

Upvotes: 2

theninjagreg
theninjagreg

Reputation: 1756

You could shorten it to:

var dm = detailmetrics.FirstOrDefault(dm => dm.MetricScopeID == 2 && dm.MetricTypeID == 1 && dm.Timeframe.Equals("C"));
if (dm != null) {
    currentPopulation = Convert.ToDouble(dm).MetricValue;
}

That way you only evaluate the FirstOrDefault once.

Upvotes: 0

Related Questions