是否可以在C#中覆盖类的null-coalescing运算符?
比如说,如果实例为null,我想返回一个默认值,如果不是,则返回实例。代码看起来像这样:
return instance ?? new MyClass("Default");
但是如果我想使用null-coalescing运算符来检查是否设置了MyClass.MyValue呢?
当然没有真正的需要(至少我是这么认为) - 所以在你回答“你为什么要这样做”之前 - 我只是好奇,如果可能的话。< / p>
答案 0 :(得分:29)
好问题!它未在list of overloadable and non-overloadable operators中以这种或那种方式列出,the operator's page上没有提到任何内容。
所以我尝试了以下内容:
public class TestClass
{
public static TestClass operator ??(TestClass test1, TestClass test2)
{
return test1;
}
}
我收到错误“可加载二进制运算符”。所以我要说答案是,从.NET 3.5开始,没有。
答案 1 :(得分:14)
答案 2 :(得分:7)
简单回答:否
C#设计原则不允许运算符重载改变语言的语义。因此,复合赋值,三元运算符和...等复杂运算符不能重载。
答案 3 :(得分:3)
据传,这是下一版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;
答案 4 :(得分:0)
我试图用我写的与Nullable<T>
非常相似的结构来实现这一点。使用Nullable<T>
,您可以执行类似的操作
Nullable<Guid> id1 = null;
Guid id2 = id1 ?? Guid.NewGuid();
尽管id1
仅defines an explicit
conversion可以键入Nullable<Guid>
,但将Guid
从Nullable<T>
隐式转换为T
没问题。用我自己的类型做同样的事情,会给出错误
操作员“ ??”不能应用于类型为'MyType'的操作数,并且 '导游'
因此,我认为编译器内置了一些魔术,可以为Nullable<T>
做一个特殊的例外。所以作为替代方案...
我们不能覆盖??
运算符,但是如果您希望合并运算符评估一个基础值而不是类(或者在我的情况下为struct)本身,则可以使用一种导致很少需要额外的击键。上面的案例看起来像这样:
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
本身实际上不能为null。对于一个类,只要暴露您要检查的值,扩展方法就可以处理实例是否为空:
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";
答案 5 :(得分:-2)
如果有人在这里寻找解决方案,最接近的例子就是这样做
return instance.MyValue != null ? instance : new MyClass("Default");