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

发布于 2024-08-10 01:02:02 字数 809 浏览 6 评论 0原文

这是 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# 不能隐藏不安全和指针背后的丑陋之处?即使我选择采用这种丑陋的解决方法,它也无法在 Silverlight 中工作,因为 Silverlight 不允许不安全的操作......

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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

指尖微凉心微凉 2024-08-17 01:02:02

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

例如,

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.

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.
橘香 2024-08-17 01:02:02

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

I think it is because an operator (in the more mathematical view that C# seems to take) is logically something that combines its arguments into a new value, never supposed to be mutating anything. C++ seems to consider operators more as a version of general operations with more convenient syntax than functions, than as a way to represent maths in particular. I think that in C# you'll almost never see things like defining operators for stream operations and such.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文