具有不同类型操作数的空合并运算符

Null-coalescing operators with operands of different types

我知道您不能将不同的类型组合成一个结果,但我不明白为什么会这样。

例如

Guid? ID;
int ID2;
var ID3 = ID ?? ID2;

以上代码不起作用,无论 ID 的可空性或 ID3、var、object 等的类型如何

谁能解释为什么不允许这样做?

我的实际代码如下所示:

public StandAloneMachine Get(int id, Guid? FKGuid = null, string FKName = "") 
{ 
    var parameters = new Parameters() 
    { 
        new Parameter("id", FKGuid ?? id) 
    }; 
}

Does anyone have a reason why this isn't allowed?

这就是语言的设计方式。它应该做什么?您如何将 32 位数字 int 转换为由多个数字部分组成的结构 GUID,反之亦然?

此代码:

var ID3 = ID ?? ID2

翻译成类型表示(伪代码):

(inferred type_) = Guid? ?? int;

?? 运算符自然要求其参数类型兼容。实际规则相当复杂,可以在 in the C# language specification here.

中找到

无论如何,空合并运算符 returns 必须将单个值及其左右参数计算为同一类型的值。因此,结果可能是 Guidint(inferred type) 就是这种类型。但是,?? 无法将 Guidint 操作数的值转换为这种单一类型的值。

注意:您可能会争辩说编译器可以选择 object 作为与 Guidint 兼容的关闭类型,并将这些值装箱到一个对象中。但是,这会破坏强类型检查的意义。它只是 'too relaxed'.

在您的特定示例中,坚持使用 ?? 似乎是人为的;一个好的旧 ?: 和你的代码中多一点表现力会做得更好,甚至可能有助于提高可读性:

var parameters = new Parameters() 
{ 
    new Parameter("id", FKGuid.HasValue ? ToTypeParameterExpects(FKGuid.Value) : ToTypeParameterExpects(id)) 
}; 

显然,ToTypeParameterExpects 是对 Parameter 的构造函数期望值的任何类型的转换。