5

假设,我有以下简化类型:

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

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

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

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

更好的解决方法

CodeExpression等于model.Result.GetValueOrDefault(0M)适用于可空值类型

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

1 回答 1

3

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

尝试使用下一个代码,即简单地调用 GetValueOrDefault方法 via CodeMethodInvokeExpression,这在语义上等效于调用 null 合并运算符。我将4其用作默认值,但在您的情况下,省略该参数即可,因为您需要0m作为小数的默认值。

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

注意:经过检查GetValueOrDefault我发现,它使用HasValue属性。所以没有必要调用它两次(所以编译器会在??没有优化的情况下调用它两次。如果启用了优化,它只会调用GetValueOrDefault)。方法内容如下:

public T GetValueOrDefault(T defaultValue)
{
  if (!this.HasValue)
    return defaultValue;
  else
    return this.value;
}
于 2013-04-10T23:24:12.610 回答