为什么C#不支持运算符重载并通过引用传递?

Iva*_*nov 6 c# clr c++-cli operator-overloading command-line-interface

这是CLR限制还是语言设计决定?我尝试在C++/CLI中进行,当然它的工作原理是因为需要支持本机c ++:

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

            return nullptr;
        } 
    };
Run Code Online (Sandbox Code Playgroud)

然后看了编译器省略的输出:

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

我走得更远,试图从C#项目调用这个操作符 - 当然我需要[不安全]来做它(我需要指针):

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

unsafe
{
    t = t & &i;
} 
Run Code Online (Sandbox Code Playgroud)

CLR显然没那么难实现?我真的很想念运营商超载中的参考文献,并且至少想知道为什么这会丢失?

当我们需要在运算符重载中处理引用变量时,为什么C#不能隐藏不安全和指针背后的丑陋?即使我选择使用这种丑陋的解决方法,它也不适用于不允许不安全操作的Silverlight ...

Meh*_*ari 5

在C#中,如果没有显式地将它们作为引用传递(例如int.TryParse(s, out i),您明确指定out关键字的位置),则您的变量永远不会被被调用者更改.通过允许重载操作符在未经您明确许可的情况下更改操作数的内容,此功能会使事情变得复杂.

例如,

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

当您在C#中引用此类运算符时:

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

  • Ivan:C#旨在克服C++的复杂性."如果我真的需要改变一个不是参考类型的操作数怎么办?我该怎么做?" 首先,如果你真的需要它,你应该创建一个方法,而不是为此目的的运算符.您正在滥用运算符重载.第二,如果被调用者没有意识到你的决定并且突然看到他的变量在表达式中被修改了怎么办?这将导致调试中的麻烦. (4认同)
  • 允许类型使用第一个参数是“ref”类型的方法覆盖诸如“+=”之类的东西会产生完全符合预期的语义,但会允许某些类型以更有效或提供的方式实现此类运算符由于通常实现了“+=”运算符,因此线程安全性比可能的更好。 (2认同)
  • 我不得不同意这可以以可预测的方式内联并且肯定会有好处。主要示例:用于图形应用程序的用户定义矩阵类型的运算符重载。4x4 矩阵是在每次调用时按值传递的重磅炸弹,这就是为什么我们经常求助于创建利用传递引用功能的函数调用,即使对于我们无意允许任何一个的等式比较等方法要更改的操作数。允许运算符重载使用相同的语义对此非常有用。 (2认同)