是否可以为 C# 中的类重载空合并运算符?
例如,如果实例为空,我想返回一个默认值,如果不是,则返回该实例。代码看起来像这样:
return instance ?? new MyClass("Default");
但是,如果我想使用 null-coalescing 运算符来检查 MyClass.MyValue 是否已设置,该怎么办?
是否可以为 C# 中的类重载空合并运算符?
例如,如果实例为空,我想返回一个默认值,如果不是,则返回该实例。代码看起来像这样:
return instance ?? new MyClass("Default");
但是,如果我想使用 null-coalescing 运算符来检查 MyClass.MyValue 是否已设置,该怎么办?
好问题!它没有在可重载和不可重载运算符列表中以一种或另一种方式列出,并且在运算符页面上没有提及任何内容。
所以我尝试了以下方法:
public class TestClass
{
public static TestClass operator ??(TestClass test1, TestClass test2)
{
return test1;
}
}
我收到错误“预期可重载的二进制运算符”。所以我想说,从 .NET 3.5 开始,答案是否定的。
简单的回答:没有
C# 设计原则不允许改变语言语义的运算符重载。因此复合赋值、三元运算符和...等复杂运算符不能重载。
据传这将成为下一版本 C# 的一部分。来自http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated
7. Monadic null 检查
无需在访问属性或方法之前检查空值。在 Groovy 中称为安全导航运算符)。
前
if (points != null) {
var next = points.FirstOrDefault();
if (next != null && next.X != null) return next.X;
}
return -1;
后
var bestValue = points?.FirstOrDefault()?.X ?? -1;
我试图用我写的一个非常相似的结构来完成这个Nullable<T>
。有了Nullable<T>
你可以做类似的事情
Nullable<Guid> id1 = null;
Guid id2 = id1 ?? Guid.NewGuid();
尽管只定义了到 type的转换id1
,但隐式转换fromNullable<Guid>
到 a没有问题。用我自己的类型做同样的事情,它给出了一个错误Guid
Nullable<T>
explicit
T
操作员 '??' 不能应用于“MyType”和“Guid”类型的操作数
所以我认为编译器内置了一些魔法来为Nullable<T>
. 所以作为替代...
我们不能覆盖??
操作符,但是如果您希望合并操作符评估基础值而不是类(或在我的情况下为结构)本身,您可以只使用一种方法,从而需要很少的额外击键。在我上面的案例中,它看起来像这样:
public struct MyType<T>
{
private bool _hasValue;
internal T _value;
public MyType(T value)
{
this._value = value;
this._hasValue = true;
}
public T Or(T altValue)
{
if (this._hasValue)
return this._value;
else
return altValue;
}
}
用法:
MyType<Guid> id1 = null;
Guid id2 = id1.Or(Guid.Empty);
这很好用,因为它是一个结构,并且id1
它本身实际上不能为空。对于一个类,扩展方法可以处理实例是否为空,只要您尝试检查的值是公开的:
public class MyClass
{
public MyClass(string myValue)
{
MyValue = myValue;
}
public string MyValue { get; set; }
}
public static class MyClassExtensions
{
public static string Or(this MyClass myClass, string altVal)
{
if (myClass != null && myClass.MyValue != null)
return myClass.MyValue;
else
return altVal;
}
}
用法:
MyClass mc1 = new MyClass(null);
string requiredVal = mc1.Or("default"); //Instead of mc1 ?? "default";
如果有人在这里寻找解决方案,最接近的例子就是这样做
return instance.MyValue != null ? instance : new MyClass("Default");