防止隐式操作符中的覆盖
本文关键字:覆盖 操作符 | 更新日期: 2023-09-27 18:17:44
我有一个小类,我们称之为uomvalue,它包含一个UOM和一个Value字段。
我有一个隐式操作符,当直接应用时,它将double类型转换为Value字段。
所以如果我使用"正常"的方式,一切都很好:
obj.UOM = "ft";
obj.Value = 123.4; //normal assignment
我的问题是,当我使用隐式操作符赋值时:
obj = 123.4; //impl op assignement
…整个对象将被替换,并且我可能已经对UOM进行的任何赋值都将丢失。
这可能属于"愚蠢的问题"类别,因为我真的没有花任何时间来弄清楚这个问题,但是是否有一种简单的方法可以做到这一点,当impl时,我可以保留UOM的旧值。使用Op. ?
最简单的回答:不要从double
隐式转换。在我看来,像这样的隐式转换几乎总是一个坏主意。(也有例外,但听起来不像是其中之一。)
我觉得隐式转换也更适合不可变类型,你所描述的情况根本不会发生。在我看来,如果没有这个隐式转换,你的代码肯定会更清晰。例如:
obj = SomeClass.FromDouble(123.4);
的作用是显而易见的。
不,你不能写一个隐式操作符,试图保留一个现有的值。毕竟,转换都发生在赋值之前——表达式123.4
中没有任何关于obj
的信息……因此,你必须让赋值运算符本身知道,它应该使用要赋给的变量值的一部分,作为计算要赋给的值的一部分。当事先没有这样的值时,就会出现问题。
所有这些都变得很复杂:放弃转换:)
取消隐式强制转换。
隐式强制转换会破坏信息(即UOM
字段)。
隐式强制转换应始终保留源对象中的所有信息。
如果目标类型比源类型窄,则使用显式强制转换。
这就是为什么uint
隐式强制转换为double
而不是int
的原因。
而且,因为你的类型代表一个值,它应该是不可变的
我记得有一位小学老师,在需要的时候,他会对任何涉及一个单位的答案做出回应,问"什么?"羊吗?米?英镑?年?"。
你有一个类,它意味着有这个问题的答案,隐式操作符删除了它。
x = 6.0
你在说"x现在等于6.0"。不是"x现在等于6.0是它的数字方面,在其他方面没有改变",而是"x现在等于6.0"
由于这个原因,即使你所尝试的是可能的,对于显式操作符来说也是一个糟糕的设计,更不用说隐式操作符了。
反过来就是另一回事了。
UnitMeasure um = new UnitMeasure(6.0, Units.Meter);
double d = (double)um;
那么对于代码的调用者来说,当我们将6.0米赋值给double类型时,double类型现在包含6.0米。我仍然希望它是显式的而不是隐式的(它会丢失信息),有些人可能会对强制转换覆盖保持足够的警惕,以避免它(无论哪种方式都有很好的参数),但至少它有意义。
在一天结束的时候,你是在为人类和机器写代码。如果你没有写一些有意义的东西,或者更糟糕的是强迫别人写一些没有意义的东西,那么你的设计可以得到改进,"这个数字和一个单位的组合等于6"是没有意义的。
除了
,隐式操作符(以及显式操作符)像它们那样覆盖的原因是,这正是它们的作用。(int)3.2
创建了一个全新的int
。(double)76
创建了一个全新的double。
obj = 123.4;
和
UnitMeasure temp = new UnitMeasure(123.4);
obj = temp;
如何不覆盖obj?
唯一不创建新对象的强制转换形式是向上强制转换和向下强制转换,它们改变的是对象的使用方式,而不是对象本身:
string s = "abc";
object o = s;//implicit - but s was already an object!
string s2 = (string)o;//explicit - but o was already a string! (and it would throw otherwise).
这些形式不会改变对象的某些部分,因为它们不会改变对象的任何部分。
在一天结束时,你会问如何实现一个不像隐式强制转换的隐式强制转换。谢天谢地,你不能。