C# 如何使用CodeDOM表示空合并运算符?
比方说,我有以下简化类型:C# 如何使用CodeDOM表示空合并运算符?,c#,codedom,null-coalescing-operator,C#,Codedom,Null Coalescing Operator,比方说,我有以下简化类型: public class Model { public decimal? Result { get; set; } } 如何使用CodeDOM来表示空合并操作符来生成C#代码,可能吗? 现在,我使用以下变通方法: new CodePropertyReferenceExpression( new CodePropertyReferenceExpression(modelArgument, "Result"), &qu
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.getValuerDefault(0M)
适用于可为空的值类型
new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(
new CodePropertyReferenceExpression(modelArgument, "Result"),
"GetValueOrDefault"),
new [] { new CodePrimitiveExpression(0m) })),
正如大家在评论部分提到的,
??
操作符只是一个语法糖。如果检查IL
代码,您将看到HasValue
上的条件,然后调用GetValueOrDefault
方法。此方法接受一个参数,如果可为null的对象没有值,则将返回该参数,在其他情况下,它将返回value
property
尝试使用下一个代码,即通过codemethodinvokeeexpression
调用GetValueOrDefault
方法,这在语义上等同于调用null coalesing操作符。我使用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;
}
想一想,你有没有试过用一个空合并操作符编写一个简单的POCO,并查看在IL Dasm或reflector中生成的代码?@RussC我试过了。
model.Result??0M
与model.Result.HasValue相同吗?model.Result.getValuerDefault():0M我想可能是这样的;空合并只是一个编译器技巧;这应该会给你一个更好的线索,关于发射什么。从我所读到的内容来看,与其让一个发出三元运算符(这似乎是不允许的)发出一个If..Else块,不如基于以下链接:为什么不直接使用model.Result.GetValueOrDefault()
?或者您还需要支持其他默认值吗?