【发布时间】:2018-09-20 15:02:22
【问题描述】:
以下内容无法编译:
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? to long 会导致该行编译,但 'Foo bar2 = (long?)null' 会失败(需要显式转换)。
我的问题是;有没有办法让 'Foo bar4 = null' 也能正常工作,或者这只是语言的限制(例如,我不能添加一个 'null' 运算符或告诉它使用哪个运算符来表示 null)?
我意识到我可以将结构更改为类,但我不希望它为 null,我希望能够让 null 创建它的实例。
编辑:我应该补充一点,我知道有很多方法可以解决这个问题,但是由于 '= null'(本质上是执行 'new Foo()')只适用于其中一个隐式运算符,我只是想知道是否有可能让它仍然与它们一起工作(我觉得语言中应该有一种方法可以做到这一点 - 现在或将来,不是吗?)。
【问题讨论】:
-
Is there a way to make 'Foo bar4 = null' work as well -
您的结构不可为空,因为您引入了一个强制转换,可以将空值强制转换为该类型。事实上,
struct本身从不为空,但对它的引用可能是,但仅当它们的类型为Nullable<Foo>时。 -
是的,如果您希望值类型为
null,请将其设置为Nullable<>。如果您想将其视为new Foo()(就像您在隐式运算符中使用的那样),请使用Foo bar4 = default(Foo);。通过这种方式,如果是class,您将获得null;如果是struct,您将获得new Foo()。 -
对我来说没有多大意义。如果在编写代码期间您知道需要将默认值(或您为
(long?)null分配的任何值)分配给Foo,您可以直接分配它。 -
你可以编写一个带有
object参数的第三重载,你可以检查它是否为空。如果分配了任何现有对象,则抛出异常。缺点:如果您分配对象(显然),编译器不会警告您。像这样的东西:public static implicit operator Foo(object bar) { if (bar != null) throw new Exception(); return new Foo(); }
标签: c# struct null operator-keyword implicit-conversion