如何使用CodeDOM表示null合并运算符?

Aki*_*kim 5 c# codedom null-coalescing-operator

比方说,我有以下简化类型:

public class Model
{
    public decimal? Result { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如何使用CodeDOM表示空合并运算符来生成C#代码,它有可能吗?现在我正在使用以下解决方法:

new CodePropertyReferenceExpression(
    new CodePropertyReferenceExpression(modelArgument, "Result"),
        "Value"))
Run Code Online (Sandbox Code Playgroud)

这等于model.Result.Value,但不是model.Result ?? 0M

更好的解决方法

CodeExpressionequalent到model.Result.GetValueOrDefault(0M)适合于空值类型

new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodePropertyReferenceExpression(modelArgument, "Result"),
                            "GetValueOrDefault"),
                            new [] { new CodePrimitiveExpression(0m) })),
Run Code Online (Sandbox Code Playgroud)

Ily*_*nov 3

正如评论部分提到的,??运算符只是一个语法糖。如果您检查IL代码,您将看到条件HasValue,然后调用GetValueOrDefault方法。该方法接受一个参数,如果 Nullable 对象没有值,则返回该参数,否则返回Value属性。

尝试使用下一个代码,它只是调用 GetValueOrDefault方法 via CodeMethodInvokeExpression,这在语义上等同于空合并运算符的调用。我使用4作为默认值,但在您的情况下,省略该参数即可完成工作,因为您需要0m作为小数的默认值。

new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodePropertyReferenceExpression(modelArgument, "Result"),
                            "GetValueOrDefault"),
                            new [] { new CodePrimitiveExpression(0m) }));
Run Code Online (Sandbox Code Playgroud)

注意:经过检查GetValueOrDefault我发现,它使用了HasValue属性。因此不需要调用它两次(因此,如果使用??未经优化的运算符,编译器将调用它两次。如果启用优化,它将简单地调用GetValueOrDefault)。方法内容如下:

public T GetValueOrDefault(T defaultValue)
{
  if (!this.HasValue)
    return defaultValue;
  else
    return this.value;
}
Run Code Online (Sandbox Code Playgroud)