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

问题描述 投票:0回答:2

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

例如。

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) 
    }; 
}
c# null-coalescing-operator
2个回答
7
投票

有人知道为什么不允许这样做吗?

这就是语言的设计方式。它应该做什么?如何将

int
(32 位数字)转换为
GUID
(由多个数字部分组成的结构),反之亦然?

此代码:

var ID3 = ID ?? ID2

翻译成类型意味着(伪代码):

(inferred type_) = Guid? ?? int;

??
运算符自然要求其参数的类型兼容。实际规则相当复杂,可以在此处的 C# 语言规范中找到

无论如何,空合并运算符返回单个值,并且其左参数和右参数必须计算为相同类型的值。因此,结果可能是 either a

Guid
or an
int
(inferred type)
就是这种类型。但是,
??
无法将
Guid
int
操作数的值转换为此类单一类型的值。

注意:您可能会认为编译器可以选择

object
作为与
Guid
int
兼容的关闭类型,然后将这些值装箱到一个对象中。然而,这会破坏强类型检查的真正意义。那就‘太放松’了。

在您的特定示例中,坚持使用

??
似乎是人为的;一个好的旧的
?:
以及代码中更多的表现力会做得更好,甚至可能有助于提高可读性:

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

显然,

ToTypeParameterExpects
是到
Parameter
的构造函数期望值的任何类型的转换。


0
投票

从类型安全的角度来看,

object ID3 = ID ?? ID2;
可以,而
var ID3 = ID ?? ID2;
则不然(因为它需要凭空猜测
object
)。然而,让语言接受的工作仅针对
?:
完成( https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/target-类型化条件表达式)而不是
??

使用此方法并假设

Parameter
构造函数的第二个参数是
object
类型,可能的修复方法是
new Parameter("id", FKGuid is { } guid ? guid : id)

不过我想说

new Parameter("id", FKGuid ?? (object)id)
更好。

© www.soinside.com 2019 - 2024. All rights reserved.