Search code examples
c#clrc++-clioperator-overloadingcommand-line-interface

Why does not C# support operator overloading with pass by reference?


Is this a CLR restriction or a language design decision? I tried to do it in C++/CLI, of course where it works because the need to support native c++:

public ref class Test
    {
        public:
        static Test^ operator &( Test^ msg, int& i )
        {
            i = i + 1;

            return nullptr;
        } 
    };

and then looked at the compiler omitted output:

public: static Test __gc* op_BitwiseAnd(Test __gc* msg, Int32 __gc** modopt(IsImplicitlyDereferenced __gc*) i)
{
    i[0] += 1;
    return 0;
}

I went further and tried to call this operator from C# project - and of course I needed to go [unsafe] to do it( I needed pointer ):

Test t = new Test();
int i = 0;

unsafe
{
    t = t & &i;
} 

Obviously not so hard to implement for the CLR? I really miss pass by reference in operators overloading and would like to at least in light myself in why is this missing?

Why can't C# hide the ugliness behind the unsafe and pointers when we need to deal with reference variables in our operator overloads? Even if I chose to go with this ugly workaround it wouldn't work in Silverlight, where unsafe operations is not allowed...


Solution

  • In C#, your variables are never altered by callees without you explicitly passing them as references (e.g. int.TryParse(s, out i) where you explicitly specify the out keyword). This feature would make things complicated by allowing the overloaded operator alter the contents of the operands without your explicit permission.

    For instance,

    public static MyStruct operator + (ref MyStruct left, ref MyStruct right) {
        left = new MyStruct(); // !!!!!!!!
        return something(left, right);
    }
    

    When you reference such an operator in C#:

    MyStruct x = new MyStruct();
    MyStruct y = new MyStruct();
    MyStruct z = x + y; // in C#, you never expect `x` to be changed.