Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to express null coalescing operator using CodeDOM?

Let's say, I have following simplified type:

public class Model
{
    public decimal? Result { get; set; }
}

How to express null coalescing operator using CodeDOM to generate C# code, is it possible at all? Now I'm using following workaround:

new CodePropertyReferenceExpression(
    new CodePropertyReferenceExpression(modelArgument, "Result"),
        "Value"))

Which is equal to model.Result.Value, but not model.Result ?? 0M

Better workaround

CodeExpression equalent to model.Result.GetValueOrDefault(0M) suitable for nullable value types

new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodePropertyReferenceExpression(modelArgument, "Result"),
                            "GetValueOrDefault"),
                            new [] { new CodePrimitiveExpression(0m) })),
like image 666
Akim Avatar asked Oct 22 '22 12:10

Akim


1 Answers

As guys mentioned in the comment section, ?? operator is just a syntactical sugar. If you inspect IL code you will see condition on HasValue and then call to a GetValueOrDefault method. This method accepts a parameter, that will be returned if a Nullable object has no value, in other case it will return Value property.

Try to use next code, that simply call GetValueOrDefault method via CodeMethodInvokeExpression, which is semantically equivalent to the call of null-coallesing operator. I use 4 as a default value, but in you case omiting the parameter will do the job, because you demand 0m as a default value for a decimal.

new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodePropertyReferenceExpression(modelArgument, "Result"),
                            "GetValueOrDefault"),
                            new [] { new CodePrimitiveExpression(0m) }));

Note: after inspection of GetValueOrDefault I found, that it uses HasValue property. So there is no need to call it twice (so compiler will call it twice in case of using ?? operator without optimization. In case of optimization enabled it will simply call GetValueOrDefault). Method contents are given below:

public T GetValueOrDefault(T defaultValue)
{
  if (!this.HasValue)
    return defaultValue;
  else
    return this.value;
}
like image 72
Ilya Ivanov Avatar answered Nov 01 '22 09:11

Ilya Ivanov