Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止隐式运算符中的覆盖_C#_.net_Type Conversion - Fatal编程技术网

C# 防止隐式运算符中的覆盖

C# 防止隐式运算符中的覆盖,c#,.net,type-conversion,C#,.net,Type Conversion,我有一个小类,我们称之为uomvalue,它包含一个UOM和一个值字段 我有一个隐式运算符,当直接应用时,它将double转换为Value字段 因此,如果我以正常方式使用它,一切都很好: obj.UOM = "ft"; obj.Value = 123.4; //normal assignment 我的问题是,当我使用隐式运算符赋值时: obj = 123.4; //impl op assignement …整个对象被替换,我可能已经对计量单位进行的任何分配都将丢失 这可能属于愚蠢的问题类别

我有一个小类,我们称之为uomvalue,它包含一个UOM和一个值字段

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

因此,如果我以正常方式使用它,一切都很好:

obj.UOM = "ft"; 
obj.Value = 123.4; //normal assignment
我的问题是,当我使用隐式运算符赋值时:

obj = 123.4; //impl op assignement
…整个对象被替换,我可能已经对计量单位进行的任何分配都将丢失


这可能属于愚蠢的问题类别,因为我真的没有花任何时间来弄清楚这一点,但有没有一种简单的方法可以做到这一点,在impl时,我可以保留UOM的旧值。op.使用了什么

摆脱隐式强制转换

隐式强制转换将销毁信息,即UOM字段。 隐式强制转换应始终保留源对象中的所有信息

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

这就是为什么uint隐式转换为double而不是int


而且,由于您的类型表示一个值,所以它应该是不可变的。

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

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

obj = SomeClass.FromDouble(123.4);
就它的作用而言,这是显而易见的

不,您不能编写试图保留现有值的隐式运算符。毕竟,转换都发生在赋值之前-表达式123.4中的任何内容都不知道obj。。。因此,您必须让赋值运算符本身知道,它应该使用变量值的某个部分,该部分将被赋值,作为计算要赋值的值的一部分。如果事先没有这样的值,这就成了问题


所有这些都变得越来越复杂:放弃转换:

我记得一位小学老师会在需要时回答任何关于单元的问题,问什么?羊米?英镑?年

你有一个类,它应该有这个问题的答案,而隐式操作符会删除它。如果您这样做:

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的组合是没有意义的

撇开这一点不谈,隐式运算符和显式运算符之所以会像它们那样覆盖,是因为这正是它们的用途。int3.2创建一个全新的int。double 76创建一个全新的double

以下两者之间没有区别:

obj = 123.4;

那怎么能不写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).
这些表单不会更改对象的某些部分,因为它们不会更改对象的任何部分


在一天结束的时候,你会问如何让隐式角色转换的行为不像隐式角色转换。谢天谢地,您不能这样做。

您的uomvalue类可能应该是一个不可变的结构。而且UOM也不是一个好的字段名。@CodeInChaos:正确。它应该被称为Unit。好吧,假设这个类是从基于xml的标准生成的,因此我在设计中没有发言权。好,走,;我还要补充一件事——可以通过使用默认值在所有类上设置计量单位,因此通常情况下,计量单位没有显式设置,并且应该是默认计量单位。@boomhauer:老实说,这根本不会改变我的答案。但无论如何,你回答了一个愚蠢的问题:我们是否可以访问一些原始数据。答案由你决定,先生;
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).