防止隐式操作符中的覆盖

本文关键字:覆盖 操作符 | 更新日期: 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).

这些形式不会改变对象的某些部分,因为它们不会改变对象的任何部分。

在一天结束时,你会问如何实现一个不像隐式强制转换的隐式强制转换。谢天谢地,你不能。