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

为什么C#不支持通过引用传递的运算符重载?,c#,clr,c++-cli,operator-overloading,command-line-interface,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; } }; 然后查看编译器忽

这是CLR限制还是语言设计决策?我尝试在C++/CLI中实现它,当然是在它工作的地方,因为需要支持原生C++:

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

            return nullptr;
        } 
    };
然后查看编译器忽略的输出:

public: static Test __gc* op_BitwiseAnd(Test __gc* msg, Int32 __gc** modopt(IsImplicitlyDereferenced __gc*) i)
{
    i[0] += 1;
    return 0;
}
我更进一步,试着从C#project打电话给这个接线员——当然,我需要去[不安全的]去做(我需要指针):

显然,对于CLR来说实现起来不是那么难吗?我真的很怀念操作符重载中的passbyreference,我想至少告诉自己为什么会缺少这个

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

在C#中,如果您不将变量作为引用显式传递给被调用方,则被调用方永远不会更改变量(例如,
int.TryParse(s,out I)
其中您显式指定
out
关键字)。此功能允许重载运算符在没有您明确许可的情况下更改操作数的内容,从而使事情变得复杂

比如说,

public static MyStruct operator + (ref MyStruct left, ref MyStruct right) {
    left = new MyStruct(); // !!!!!!!!
    return something(left, right);
}
在C#中引用此类运算符时:


我认为这是因为一个操作符(在C#似乎采取的更数学的观点中)在逻辑上是将其参数组合成一个新值的东西,不应该是任何变异。C++似乎把操作符更多地看成是一个通用操作的版本,它比函数更方便的语法,而不是一种特别地表示数学的方式。我认为在C#中,你几乎不会看到为流操作定义操作符之类的事情。

一点也不会。只需让操作员重载来获取REF参数?伊凡:C是设计不克隆C++复杂度的。“如果我真的需要修改一个不是引用类型的操作数,该怎么做?”首先,如果你真的需要它,你应该创建一个方法,而不是一个操作符。您正在滥用运算符重载。其次,如果被调用方没有意识到您的决定,并且突然看到他的变量在表达式中被修改,该怎么办?这将导致调试中的麻烦。“如果我真的需要修改一个不是引用类型的操作数,该怎么做?”请改用方法。我认为在任何情况下都不需要运算符,特别是这样的运算符。允许类型使用第一个参数为
ref
类型的方法重写
+=
之类的内容将产生完全符合预期的语义,但是会允许某些类型以一种比通常实现
+=
操作符更高效或提供更好的线程安全性的方式实现此类操作符。我必须同意,这可以以一种可预测的方式内联,并且肯定会带来好处。主要示例:在图形应用程序中使用的用户定义矩阵类型上的运算符重载。4x4矩阵是在每次调用时按值传递的炸弹,这就是为什么我们经常求助于创建函数调用,使用按引用传递功能,即使对于等式比较之类的方法,我们也不打算允许更改任何一个操作数。允许对操作符重载使用相同的语义将是非常好的。C#有
++
--
操作符,这使得整行参数都有问题。
public static MyStruct operator + (ref MyStruct left, ref MyStruct right) {
    left = new MyStruct(); // !!!!!!!!
    return something(left, right);
}
MyStruct x = new MyStruct();
MyStruct y = new MyStruct();
MyStruct z = x + y; // in C#, you never expect `x` to be changed.