可以重载空合并运算符吗?

发布于 2024-07-10 02:58:33 字数 212 浏览 7 评论 0原文

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

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

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

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

Is it possible to overload the null-coalescing operator for a class in C#?

Say for example I want to return a default value if an instance is null and return the instance if it's not. The code would look like something like this:

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

But what if I would like to use the null-coalescing operator to also check if the MyClass.MyValue is set?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

々眼睛长脚气 2024-07-17 02:58:34

据传这是 C# 下一版本的一部分。 来自http://damieng.com/blog/ 2013/12/09/probable-c-6-0-features-illustrator

7。 Monadic null 检查

在访问属性或方法之前无需检查 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;

This is rumored to be part of the next version of C#. From http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated

7. Monadic null checking

Removes the need to check for nulls before accessing properties or methods. Known as the Safe Navigation Operator in Groovy).

Before

if (points != null) {
    var next = points.FirstOrDefault();
    if (next != null && next.X != null) return next.X;
}   
return -1;

After

var bestValue = points?.FirstOrDefault()?.X ?? -1;
雨落□心尘 2024-07-17 02:58:34

我试图用我编写的一个非常相似的 Nullable 结构来完成此任务。 使用 Nullable 您可以执行类似的操作,

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

id1Nullable 隐式转换为 Guid< 没有问题/code> 尽管事实上 Nullable定义到类型 T显式转换。 用我自己的类型做同样的事情,它给出了一个错误

运算符“??” 不能应用于“MyType”类型的操作数并且
“指导”

所以我认为编译器中内置了一些魔法,可以为 Nullable 提供特殊的例外。 因此,作为替代方案...

tl;dr

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

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。 对于类,只要您尝试检查的值公开,扩展方法就可以处理实例是否为 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";

I was trying to accomplish this with a struct I wrote that was very similar Nullable<T>. With Nullable<T> you can do something like

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

It has no problem implicitly converting id1 from Nullable<Guid> to a Guid despite the fact that Nullable<T> only defines an explicit conversion to type T. Doing the same thing with my own type, it gives an error

Operator '??' cannot be applied to operands of type 'MyType' and
'Guid'

So I think there's some magic built into the compiler to make a special exception for Nullable<T>. So as an alternative...

tl;dr

We can't override the ?? operator, but if you want the coalesce operator to evaluate an underlying value rather than the class (or struct in my case) itself, you could just use a method resulting in very few extra keystrokes required. With my case above it looks something like this:

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;
    }
}

Usage:

MyType<Guid> id1 = null;
Guid id2 = id1.Or(Guid.Empty);

This works well since it's a struct and id1 itself can't actually be null. For a class, an extension method could handle if the instance is null as long as the value you're trying to check is exposed:

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;
    }
}

Usage:

MyClass mc1 = new MyClass(null);
string requiredVal = mc1.Or("default"); //Instead of mc1 ?? "default";
吐个泡泡 2024-07-17 02:58:34

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

return instance.MyValue != null ? instance : new MyClass("Default");

If anyone is here looking for a solution, the closest example would be to do this

return instance.MyValue != null ? instance : new MyClass("Default");
那伤。 2024-07-17 02:58:33

好问题! 它没有以某种方式列在可重载和不可重载运算符列表 并且运营商页面上没有提及任何内容。

所以我尝试了以下操作:

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

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

Good question! It's not listed one way or another in the list of overloadable and non-overloadable operators and nothing's mentioned on the operator's page.

So I tried the following:

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

and I get the error "Overloadable binary operator expected". So I'd say the answer is, as of .NET 3.5, a no.

深陷 2024-07-17 02:58:33

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

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

  • =
  • &&
  • ||
  • ?:
  • ?。
  • 检查
  • 未检查的
  • 类型
  • 原样

According to the ECMA-334 standard, it is not possible to overload the ?? operator.

Similarly, you cannot overload the following operators:

  • =
  • &&
  • ||
  • ?:
  • ?.
  • checked
  • unchecked
  • new
  • typeof
  • as
  • is
惜醉颜 2024-07-17 02:58:33

简单的答案:没有

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

Simple answer: No

C# design principles do not allow operator overloading that change semantics of the language. Therefore complex operators such as compound assignment, ternary operator and ... can not be overloaded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文