通常,对于value(struct)类型,与null(或对象类型)的比较将导致编译器错误。
struct Value
{
}
class Program
{
static void Main()
{
object o = new object();
Value v = default;
// Error CS0019 Operator '==' cannot be applied to operands of type 'Value' and '<null>'
var a = v == null;
// Error CS0019 Operator '==' cannot be applied to operands of type 'Value' and 'object'
var b = v == o;
}
}
但是,如果我在结构上添加相等运算符重载,则与null的比较不再产生编译器错误:
struct Value
{
public static bool operator ==(Value l, Value r)
{
return true;
}
public static bool operator !=(Value l, Value r)
{
return true;
}
}
class Program
{
static void Main()
{
object o = new object();
Value v = default;
// compiler is now happy with this.
var a = v == null;
// Error CS0019 Operator '==' cannot be applied to operands of type 'Value' and 'object'
var b = v == o;
}
}
我认为这与隐式转换为Nullable<Value>
有关,但我无法记住细节。问题是:是否可以在保留编译器错误的同时在结构上重载这些运算符?
我已经重构了一些代码,我认为由于这个问题,代码库中有一些地雷。我还担心未来的代码可能会意外地以这种形式编写,我真的很喜欢它产生编译错误(无需实现分析器)。
答案 0 :(得分:1)
这是因为编译器会自动生成所谓的提升运算符,这些运算符也可以使用可空值类型,因为您可以在docs中读取。因此,对于给定的比较运算符T, U -> bool
,其中T
和U
是不可为空的值类型,还存在提升的运算符T?, U -> bool
,T, U? -> bool
和T?, U? -> bool
。
要取消这些运算符,您可以明确定义它们并使用Obsolete
属性进行装饰,error
参数设置为true
,如下所示:
struct Value
{
public static bool operator ==(Value l, Value r)
{
return true;
}
public static bool operator !=(Value l, Value r)
{
return true;
}
[Obsolete("Some error message", error: true)]
public static bool operator ==(Value? l, Value r) =>
throw new NotImplementedException();
[Obsolete("Some error message", error: true)]
public static bool operator ==(Value l, Value? r) =>
throw new NotImplementedException();
[Obsolete("Some error message", error: true)]
public static bool operator ==(Value? l, Value? r) =>
throw new NotImplementedException();
[Obsolete("Some error message", error: true)]
public static bool operator !=(Value? l, Value r) =>
throw new NotImplementedException();
[Obsolete("Some error message", error: true)]
public static bool operator !=(Value l, Value? r) =>
throw new NotImplementedException();
[Obsolete("Some error message", error: true)]
public static bool operator !=(Value? l, Value? r) =>
throw new NotImplementedException();
}
现在在new Value() == null
和new Value() == (Value?)null
等比较中,将选择上述匹配的用户定义运算符,因为它更具体,并且会给出这样的错误:
错误CS0619:&#39; Value.operator ==(价值,价值?)&#39;已过时:&#39;一些错误消息&#39;