将我的类转换为Int64,Double等

相关问题: 不使用点运算符访问Class属性

我创建了一个名为MyDouble的类,如下所示

 class MyDouble { double value; //overloaded operators and methods } 

我可以在MyDouble上进行各种操作。 例子:

 MyDouble a = 5.0; a += 3.0; ...etc 

但是,这仍然会引发错误

 MyDouble a = 5.0; long b = (Int64)a; //error long b = (int64)a.value; //works 

如何定义它以使像(Int64)a这样的操作自动转换为(Int64)a.value ? 我不希望用户永远不必担心value属性的存在。

为了使此转换起作用,您需要显式转换为Int64。

这看起来像:

 class MyDouble { double value; public static explicit operator Int64(MyDouble value) { return (Int64)value.value; } } 

有一个从double到Int64的显式转换,但不是从你的类到Int64。 你需要做的就是定义一个。 或者,如果你有一个从你的class级到双倍的转换,我想你这样做,你可以这样做:

long x =(long)(double)a;

然而,这很麻烦; 我定义了显式转换运算符。

转换应该是显式的,而不是隐式的,除非您有充分的理由将其明确化。

从double到long的语言定义转换是显式的, 因为转换可能导致信息丢失。 您可以通过此转换丢失信息,因为有一些双精度数,如0.5, 不会完全转换为long。 这称为缩小转换

使用语言定义的转换,缩小转换是明确的。 如果它们是隐含的,程序员可能会通过将一种类型的值分配给另一种类型的变量而意外丢失信息。 将此转换定义为隐含违反了完全合理的原则,因此必须有一些令人信服的理由。

这是一个显示这个原则的价值的例子。 如果缩小转换是隐含的,则会使代码更脆弱。 假设double-int转换是隐式的:

 class Family { ICollection Children { get; set; } } int GetAverageNumberOfChildren(IEnumerable families) { return families.Sum(f => f.Children.Count) / families.Count(); } void SomeMethod(IEnumerable families) { int averageNumberOfChildren = GetAverageNumberOfChildren(families); //... } 

哎呀! 我们有一个错误! GetAverageNumberOfChildren应该返回一个双! 我们来解决它吧!

 double GetAverageNumberOfChildren(IEnumerable families) { return families.Average(f => f.Children.Count); } 

哇,一切都编译并运行! 很高兴我们抓住了那个虫子!

但是,遗憾的是,没有。 我们还有一个bug! SomeMethod隐式将double转换为int,因此预期值可能为2.4 ,实际值为2

因为double-int转换是显式的 ,所以编译器将我们从自己身上拯救出来。 修复GetAverageNumberOfChildren错误的程序无法编译。

现在,如果您的MyDouble类有一些validation将其限制为范围等于或小于long范围的整数值,那么您可以安全地隐式转换。 但在那种情况下,当然,你应该使用long而不是double

隐式转换既可以使用,也可以进行显式转换。

 public static implicit operator long(MyDouble m) { return (long) m.value; } 

有了这个,你可以做到:

 long b = (Int64) a; 

要不就

 long b = a; 

这只是为了说明转换不需要明确。 但是,如上所述,由于数据丢失的可能性,它应该是明确的。