为什么 C# 不支持通过引用传递的运算符重载?
这是 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 C# 中,除非您显式地将变量作为引用传递,否则您的变量永远不会被被调用者更改(例如,您显式指定
out
关键字的int.TryParse(s, out i)
) 。此功能允许重载运算符在未经您明确许可的情况下更改操作数的内容,从而使事情变得复杂。例如,
当您在 C# 中引用此类运算符时:
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 theout
keyword). This feature would make things complicated by allowing the overloaded operator alter the contents of the operands without your explicit permission.For instance,
When you reference such an operator in C#:
我认为这是因为运算符(从 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.