6

这是 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 中工作,不允许不安全的操作......

4

2 回答 2

5

int.TryParse(s, out i)在 C# 中,除非您明确地将它们作为引用传递(例如,在您明确指定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.
于 2009-10-31T16:08:41.090 回答
1

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

于 2009-10-31T16:15:26.660 回答