我知道你不能将不同的类型组合成一个结果,但我不明白为什么这是这样的。
例如。
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)
};
}
有人知道为什么不允许这样做吗?
这就是语言的设计方式。它应该做什么?如何将
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
的构造函数期望值的任何类型的转换。
从类型安全的角度来看,
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)
更好。