以下不编译:
public struct Foo
{
public static implicit operator Foo(string bar)
{
return new Foo();
}
public static implicit operator Foo(long? bar)
{
return new Foo();
}
public static void Test()
{
Foo bar = 0;
Foo bar2 = (long?)null;
Foo bar3 = "";
Foo bar4 = null; // Cannot convert null to 'Foo' because it is a non-nullable value type
}
}
'Foo bar4 = null' 失败,大概是因为编译器不知道要使用哪个隐式运算符,因为从 long 更改运算符?太长会导致该行编译,但 'Foo bar2 = (long?)null' 会失败(需要显式转换)。
我的问题是;有没有办法让“Foo bar4 = null”也能正常工作,或者这只是语言的限制(我不能添加“null”运算符或告诉它使用哪个来表示 null)?
我意识到我可以将结构更改为一个类,但我不希望它为空,我希望能够让空创建它的一个实例。
编辑: 我应该补充一点,我知道有很多方法可以解决这个问题,但是由于“= null”(本质上执行“new Foo()”)只能使用以下一种方法隐式运算符,我只是想知道是否有可能让它仍然与它们一起工作(我觉得语言中应该有一种方法可以做到这一点 - 现在或将来,不是吗?)。
最佳答案
My question is; Is there a way to make 'Foo bar4 = null' work as well, or is this just a limitation of the language (that I cannot add a 'null' operator or tell it which one to use for null for instance)?
根据这个问题和你的编辑,你基本上是在问
Why does
Foo bar4 = null
compile when it does not if I add another implicit cast operator?
答案很简单。没有任何上下文的 null
是无类型的,因此编译器不知道要使用哪个运算符。为什么?好吧,支持该语言的重载解析算法不会检查您尝试将 null
分配给的对象的类型,因此它不知道您想要哪个运算符。
您可能会争辩说,可以修改 future 的语言规范来进行这种额外的分析,但团队可能认为这不值得付出努力,否则这将是一个重大变化。
在这种情况下,您能做的最好的事情就是避免强制转换。根据您的 C# 水平,您可以执行以下任一操作:
Foo bar4 = default;
Foo bar4 = default(Foo);
这会产生可用的 Foo
。这两个默认表达式和 new Foo()
都是等价的。它们都会产生一个结构,其所有字段都被清零。
有关更多信息,您可以查看 default value expressions C# 编程指南的部分。
最后,虽然您可以使用将 null
转换为结构的单个隐式转换运算符,但这并不意味着您应该。阅读该代码但不知道类型转换的人可能会质疑他们的理智几分钟。如果可以,最好不要偏离惯用代码。
关于c# - 定义两个可为 null 的隐式运算符时无法将 null 转换为 struct,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52428125/