可以覆盖null合并运算符吗?

时间:2008-12-08 10:10:20

标签: c# .net operator-overloading null-coalescing-operator

是否可以在C#中覆盖类的null-coalescing运算符?

比如说,如果实例为null,我想返回一个默认值,如果不是,则返回实例。代码看起来像这样:

   return instance ?? new MyClass("Default");  

但是如果我想使用null-coalescing运算符来检查是否设置了MyClass.MyValue呢?

当然没有真正的需要(至少我是这么认为) - 所以在你回答“你为什么要这样做”之前 - 我只是好奇,如果可能的话。< / p>

6 个答案:

答案 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)

根据ECMA-334标准,不可能超载?运营商。

同样,您不能重载以下运算符:

  • =
  • &安培;&安培;
  • ||
  • :<?/ LI>
  • 检查
  • 选中
  • typeof运算
  • 作为

答案 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();

尽管id1defines an explicit conversion可以键入Nullable<Guid>,但将GuidNullable<T>隐式转换为T没问题。用我自己的类型做同样的事情,会给出错误

操作员“ ??”不能应用于类型为'MyType'的操作数,并且 '导游'

因此,我认为编译器内置了一些魔术,可以为Nullable<T>做一个特殊的例外。所以作为替代方案...

tl; dr

我们不能覆盖??运算符,但是如果您希望合并运算符评估一个基础值而不是类(或者在我的情况下为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");