运算符重载,C#运算符重载不是没有用武之地

当年Java批判C++过于臃肿和迷宫般的语法特性,摒弃了一大堆东西包括运算符重载。ThinkingInJava一书中好像有对此事的评价,从负面讲,运算符重载的滥用容易导致语义的混乱,例如apple+person就很难推测出其背后的意图。但是没有它,像复数类Complex的四则运算就显得十分繁琐。运算符重载到底是不是鸡肋呢?个人觉得运算符重载还是有很多用武之地的,尤其适用于和数值相关的场景。下面介绍一个我遇到的案例。
现在定义了一批0到1的数值:
运算符重载,C#运算符重载不是没有用武之地运算符重载,C#运算符重载不是没有用武之地代码 double _discount0; double Discount0 { get { return _discount0; } set { ValidateRatio(value); _discount0 = value; } } double _discount1; double Discount1 { get { return _discount1; } set { ValidateRatio(value); _discount1 = value; } } double _discount2; double Discount2 { get { return _discount2; } set { ValidateRatio(value); _discount2 = value; } } void ValidateRatio(double v) { if (v < 0 || v > 1) throw new ArgumentOutOfRangeException(); }

Discount(折扣)显然是0到1之间的某个值否则抛出异常。现在比较一下使用运算符重载之后的效果。
代码 //[0,1]的数值类型 public struct RatioValue { double _value; public RatioValue(double ratio) { if (ratio < 0 || ratio > 1) throw new ArgumentOutOfRangeException(); _value = ratio; } public double Value { get { return _value; } } public static implicit operator double(RatioValue ratio) { return ratio.Value; } public static implicit operator RatioValue(double value) { return new RatioValue(value); } } //简化了的Discount RatioValue Discount0 { get; set; } RatioValue Discount1 { get; set; } RatioValue Discount2 { get; set; }


这里用到了隐式类型转换也是运算符重载的一种。显然最后Discount的定义大大简化了。并且使用起来和double类型没有区别,一切转换都有定义的RatioValue搞定,包括值域检测。
for (int i = 0; i < 10; i++) { Discount0 = new Random().NextDouble(); System.Threading.Thread.Sleep(100); Console.WriteLine((int)(Discount0 * 10)); } Console.ReadLine();

总之语法的多样性有助于降低语法噪音,缓解人的阅读压力,至少庆幸C#没有像java因噎废食而将运算符重载拒之门外。
Tags:  运算符的重载 什么是运算符重载 运算符重载友元 重载赋值运算符 运算符重载

延伸阅读

最新评论

发表评论