43

是否可以为 C# 中的类重载空合并运算符?

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

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

但是,如果我想使用 null-coalescing 运算符来检查 MyClass.MyValue 是否已设置,该怎么办?

4

6 回答 6

30

好问题!它没有在可重载和不可重载运算符列表中以一种或另一种方式列出,并且在运算符页面上没有提及任何内容。

所以我尝试了以下方法:

public class TestClass
{
    public static TestClass operator ??(TestClass  test1, TestClass test2)
    {
        return test1;
    }
}

我收到错误“预期可重载的二进制运算符”。所以我想说,从 .NET 3.5 开始,答案是否定的。

于 2008-12-08T10:29:33.537 回答
15

根据ECMA-334标准,不可能超载?? 操作员。

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

  • =
  • &&
  • ||
  • ?:
  • ?.
  • 检查
  • 未经检查
  • 新的
  • 类型
  • 作为
于 2008-12-08T10:54:50.383 回答
7

简单的回答:没有

C# 设计原则不允许改变语言语义的运算符重载。因此复合赋值、三元运算符和...等复杂运算符不能重载。

于 2008-12-08T10:16:48.900 回答
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;
于 2014-01-10T18:30:12.590 回答
0

我试图用我写的一个非常相似的结构来完成这个Nullable<T>。有了Nullable<T>你可以做类似的事情

Nullable<Guid> id1 = null;
Guid id2 = id1 ?? Guid.NewGuid();

尽管只定义了到 type的转换id1,但隐式转换fromNullable<Guid>到 a没有问题。用我自己的类型做同样的事情,它给出了一个错误GuidNullable<T>explicitT

操作员 '??' 不能应用于“MyType”和“Guid”类型的操作数

所以我认为编译器内置了一些魔法来为Nullable<T>. 所以作为替代...

tl;博士

我们不能覆盖??操作符,但是如果您希望合并操作符评估基础值而不是类(或在我的情况下为结构)本身,您可以只使用一种方法,从而需要很少的额外击键。在我上面的案例中,它看起来像这样:

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";
于 2020-04-01T18:11:41.610 回答
-3

如果有人在这里寻找解决方案,最接近的例子就是这样做

return instance.MyValue != null ? instance : new MyClass("Default");
于 2009-11-19T13:46:21.383 回答