【问题标题】:Why does not C# support operator overloading with pass by reference?为什么 C# 不支持通过引用传递运算符重载?
【发布时间】:2010-12-11 21:44:27
【问题描述】:

这是 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# 项目中调用此运算符 - 当然我需要 [不安全] 来执行此操作(我需要指针):

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

unsafe
{
    t = t & &i;
} 

显然对于 CLR 来说实现起来并不难?我真的很怀念运算符重载中的引用传递,并且想至少让自己明白为什么会丢失?

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

【问题讨论】:

    标签: c# clr c++-cli operator-overloading command-line-interface


    【解决方案1】:

    在 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# 中引用这样的运算符时:

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

    【讨论】:

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

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

    【讨论】:

    • C# 有 ++ 和 -- 运算符,这使得整行论点都有问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 2010-12-12
    • 2011-07-14
    相关资源
    最近更新 更多