为什么可以'=' 在C#中不能重载?
我想知道,为什么我不能在 C# 中重载 '=' ? 我能得到更好的解释吗?
I was wondering, why can't I overload '=' in C#? Can I get a better explanation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
能够为赋值操作定义特殊语义将是有用的,但前提是这种语义可以应用于将给定类型的一个存储位置复制到另一存储位置的所有情况。 尽管标准 C++ 实现了此类赋值规则,但它要求在编译时定义所有类型。 当反射和泛型添加到列表中时,事情会变得更加复杂。
目前,.net 中的规则指定可以通过将所有字节清零来将存储位置设置为其类型的默认值(无论该类型是什么)。 它们进一步指定可以通过复制所有字节将任何存储位置复制到相同类型的另一个存储位置。 这些规则适用于所有类型,包括泛型。 给定两个
KeyValuePair
类型的变量,系统可以将一个变量复制到另一个变量,而无需知道该类型的大小和对齐要求之外的任何信息。 如果t1
、t2
或这些类型中的任何字段的类型都可以实现复制构造函数,则编写以下代码:将一个结构体实例复制到另一个结构体实例必须要复杂得多。这并不是说这种能力提供了一些显着的好处——如果设计一个新的框架,自定义赋值运算符和默认构造函数的好处可能会超过成本。 然而,在新框架中实施成本将是巨大的,并且对于现有框架来说可能难以克服。
Being able to define special semantics for assignment operations would be useful, but only if such semantics could be applied to all situations where one storage location of a given type was copied to another. Although standard C++ implements such assignment rules, it has the luxury of requiring that all types be defined at compile time. Things get much more complicated when Reflection and and generics are added to the list.
Presently, the rules in .net specify that a storage location may be set to the default value for its type--regardless of what that type is--by zeroing out all the bytes. They further specify that any storage location can be copied to another of the same type by copying all the bytes. These rules apply to all types, including generics. Given two variables of type
KeyValuePair<t1,t2>
, the system can copy one to another without having to know anything but the size and alignment requirements of that type. If it were possible fort1
,t2
, or the type of any field within either of those types, to implement a copy constructor, code which copied one struct instance to another would have to be much more complicated.That's not to say that such an ability offer some significant benefits--it's possible that, were a new framework being designed, the benefits of custom value assignment operators and default constructors would exceed the costs. The costs of implementation, however, would be substantial in a new framework, and likely insurmountable for an existing one.
这段代码对我有用:
This code is working for me:
覆盖分配的类型
覆盖分配有两种类型:
就像浮点数到整数一样,当你丢失浮点值时
int a = (int)5.4f;
float f = 5;
如何覆盖赋值
对于 1,使用
explicit
关键字:对于 2,使用
implicit
关键字:更新:
注意:此实现可以在
FromType
或ToType
类中进行,具体取决于您的需要,没有限制,您的类之一可以保存所有转换,并且另一个没有为此实现任何代码。Type of Overriding Assignment
There are two type to Override Assignment:
like float to integer, when you loss the floating value
int a = (int)5.4f;
float f = 5;
How to Override Assignment
For 1, use of
explicit
keyword:For 2, use of
implicit
keyword:Update:
Note: that this implementation can take place in either the
FromType
orToType
class, depending on your need, there's no restriction, one of your class can hold all the conversions, and the other implements no code for this.内存管理语言通常使用引用而不是对象。 当您定义类及其成员时,您正在定义对象行为,但是当您创建变量时,您正在使用对这些对象的引用。
现在,运算符 = 应用于引用,而不是对象。 当您将一个引用分配给另一个引用时,您实际上使接收引用指向另一个引用所在的同一对象。
在上面的代码中,在堆上创建了两个对象,一个由 var1 引用,另一个由 var2 引用。 现在最后一条语句使 var2 引用指向 var1 所引用的同一个对象。 在该行之后,垃圾收集器可以释放第二个对象,并且内存中只有一个对象。 整个过程中,没有对对象本身进行任何操作。
回到为什么=不能被重载,系统实现是你可以用引用做的唯一明智的事情。 您可以重载应用于对象的操作,但不能重载应用于引用的操作。
Memory managed languages usually work with references rather than objects. When you define a class and its members you are defining the object behavior, but when you create a variable you are working with references to those objects.
Now, the operator = is applied to references, not objects. When you assign a reference to another you are actually making the receiving reference point to the same object that the other reference is.
In the code above, two objects are created on the heap, one referred by var1 and the other by var2. Now the last statement makes the var2 reference point to the same object that var1 is referring. After that line, the garbage collector can free the second object and there is only one object in memory. In the whole process, no operation is applied to the objects themselves.
Going back to why = cannot be overloaded, the system implementation is the only sensible thing you can do with references. You can overload operations that are applied to the objects, but not to references.
如果重载“=”,则在创建对象引用后将永远无法更改该对象引用。
...想一想 - 任何对 theObjectWithOverloadedOperator= 重载运算符内的内容的调用都会导致对重载运算符的另一次调用...那么重载运算符到底在做什么? 也许设置一些其他属性 - 或者将值设置为新对象(不变性)?
通常不是“=”所暗示的意思。
但是,您可以覆盖隐式的 & 。 显式转换运算符:
http://www.blackwasp.co.uk/CSharpConversionOverload.aspx
If you overloaded '=' you would never be able to change an object reference after it's been created.
... think about it - any call to theObjectWithOverloadedOperator=something inside the overloaded operator would result in another call to the overloaded operator... so what would the overloaded operator really be doing ? Maybe setting some other properties - or setting the value to a new object (immutability) ?
Generally not what '=' implies..
You can, however, override the implicit & explicit cast operators:
http://www.blackwasp.co.uk/CSharpConversionOverload.aspx
因为这样做实际上没有意义。
在 C# 中,= 将对象引用分配给变量。 因此它对变量和对象引用进行操作,而不是对对象本身进行操作。 根据对象类型来重载它是没有意义的。
在C++中,定义operator=对于可以在堆栈上创建实例的类是有意义的,因为对象本身存储在变量中,而不是对它们的引用。 因此定义如何执行此类任务是有意义的。 但即使在 C++ 中,如果您有一组通常通过指针或引用使用的多态类,您通常会通过将 operator= 和复制构造函数声明为私有(或从 boost::noncopyable 继承)来显式禁止像这样复制它们,因为与在 C# 中不重新定义 = 的原因完全相同。 简单地说,如果你有 A 类的引用或指针,你并不真正知道它是否指向 A 类的实例或 A 的子类 B 类的实例。那么你真的知道在这种情况下如何执行 = 吗?
Because it doesn't really make sense to do so.
In C# = assigns an object reference to a variable. So it operates on variables and object references, not objects themselves. There is no point in overloading it depending on object type.
In C++ defining operator= makes sense for classes whose instances can be created e.g. on stack because the objects themselves are stored in variables, not references to them. So it makes sense to define how to perform such assignment. But even in C++, if you have set of polymorphic classes which are typically used via pointers or references, you usually explicitly forbid copying them like this by declaring operator= and copy constructor as private (or inheriting from boost::noncopyable), because of exactly the same reasons as why you don't redefine = in C#. Simply, if you have reference or pointer of class A, you don't really know whether it points to an instance of class A or class B which is a subclass of A. So do you really know how to perform = in this situation?
实际上,如果您可以定义具有值语义的类
并在堆栈中分配这些类的对象,则重载operator =
是有意义的。 但是,在 C# 中,你不能。Actually, overloading
operator =
would make sense if you could define classes with value semanticsand allocate objects of these classes in the stack. But, in C#, you can't.一种可能的解释是,如果重载赋值运算符,则无法进行正确的引用更新。 它实际上会搞砸语义,因为当人们期望引用更新时,您的 = 运算符可能会完全做其他事情。 对程序员不太友好。
您可以使用隐式和显式的 to/from 转换运算符来减轻无法重载赋值的一些看似缺点。
One possible explanation is that you can't do proper reference updates if you overload assignment operator. It would literally screw up semantics because when people would be expecting references to update, your = operator may as well be doing something else entirely. Not very programmer friendly.
You can use implicit and explicit to/from conversion operators to mitigate some of the seeming shortcomings of not able to overload assignment.
我认为没有任何特别的理由可以指出。 一般来说,我认为这个想法是这样的:
如果您的对象是一个大而复杂的对象,则执行不使用
=
运算符进行赋值的操作可能会产生误导。如果您的对象是一个小对象,您也可以使其不可变并在对其执行操作时返回新副本,以便赋值运算符按您期望的开箱即用方式工作(如
System.String
确实如此。)I don't think there's any really particular single reason to point to. Generally, I think the idea goes like this:
If your object is a big, complicated object, doing something that isn't assignment with the
=
operator is probably misleading.If your object is a small object, you may as well make it immutable and return new copies when performing operations on it, so that the assignment operator works the way you expect out of the box (as
System.String
does.)您可以在 C# 中重载赋值。 只是不是在整个对象上,而是在它的成员上。 您使用 setter 声明属性:
现在,当您分配给
Real
时,您自己的代码就会运行。对对象的赋值不可替换的原因是因为它已经被语言定义为意味着非常重要的东西。
You can overload assignment in C#. Just not on an entire object, only on members of it. You declare a property with a setter:
Now when you assign to
Real
, your own code runs.The reason assignment to an object is not replaceable is because it is already defined by the language to mean something vitally important.
它在 C++ 中是允许的,如果不小心,可能会导致很多混乱和错误查找。
本文对此进行了非常详细的解释。
http://www.relisoft.com/book/lang/project/14value。 html
It's allowed in C++ and if not careful , it can result in a lot of confusion and bug hunting.
This article explains this in great detail.
http://www.relisoft.com/book/lang/project/14value.html
因为搬起石头砸自己的脚是不被允许的。
更严肃地说,人们只能希望你的意思是比较而不是分配。 该框架对干扰平等/等价评估做出了详细规定,请在帮助中或在线使用 msdn 查找“比较”。
Because shooting oneself in the foot is frowned upon.
On a more serious note one can only hope you meant comparison rather than assignment. The framework makes elaborate provision for interfering with equality/equivalence evaluation, look for "compar" in help or online with msdn.