防止隐式运算符覆盖

时间:2011-12-11 18:53:44

标签: c# .net type-conversion

我有一个小班,让我们调用uomvalue,它包含一个UOM和一个Value字段。

我有一个隐式运算符,在直接应用时将double转换为Value字段。

所以,如果我以“正常”方式使用它,一切都很好:

obj.UOM = "ft"; 
obj.Value = 123.4; //normal assignment

我的问题是当我使用隐式运算符分配时:

obj = 123.4; //impl op assignement

...整个对象被替换,我可能已经对UOM做出的任何任务都将丢失。

这可能属于“愚蠢的问题”类别,因为我真的没有花时间去解决这个问题,但有一种简单的方法可以做到这一点,我可以在impl时保留UOM的旧值。运。用来?

3 个答案:

答案 0 :(得分:3)

摆脱隐含的演员。

您的隐式演员会破坏信息(即UOM字段) 隐式强制转换应始终保留源对象中的所有信息。

如果目标类型比源类型窄,请使用显式强制转换。

这就是uint隐式转换为double而不是int的原因。


此外,由于您的类型代表一个值,因此它应该是不可变的。

答案 1 :(得分:3)

最简单的答案:没有来自double的隐式转换。像这样的隐式转换在我看来几乎总是一个坏主意。 (也有例外情况,但听起来这不是其中之一。)

我觉得隐式转换也更适合不可变类型,在这种类型中,您所描述的情况根本不会发生。在我看来,你的代码肯定会更清晰没有隐式转换。例如:

obj = SomeClass.FromDouble(123.4);

现在显而易见的是它正在做什么。

不,你不能写一个试图保留现有值的隐式运算符。毕竟,转换都发生在赋值之前 - 表达式123.4中的任何内容都不知道obj ...所以你必须让赋值运算符本身知道它应该使用某些部分的变量的值,作为计算值的一部分进行分配。当事先没有这样的值时,这就成了问题。

所有这一切都变得复杂:抛弃转换:)

答案 2 :(得分:2)

我记得一位小学老师,他会回应任何在需要时遗漏一个单位的答案,问“什么?羊?米?磅?年?”。

你有一个课程可以解决这个问题,而隐式操作员会删除它。如果你这样做:

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创造了一个全新的双倍。

之间没有区别:

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

这些表单不会更改对象的某些部分,因为它们不会更改对象的任何部分。

在一天结束时,你问的是如何进行一个不像隐式转换的隐式转换。谢天谢地,你不能。

相关问题