Possible to overload null-coalescing operator?

后端 未结 6 1930
栀梦
栀梦 2020-12-17 07:54

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 i

相关标签:
6条回答
  • 2020-12-17 08:03

    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.

    0 讨论(0)
  • 2020-12-17 08:05

    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;
    
    0 讨论(0)
  • 2020-12-17 08:10

    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
    0 讨论(0)
  • 2020-12-17 08:16

    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";
    
    0 讨论(0)
  • 2020-12-17 08:20

    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.

    0 讨论(0)
  • 2020-12-17 08:26

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

    return instance.MyValue != null ? instance : new MyClass("Default");
    
    0 讨论(0)
提交回复
热议问题