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

当年Java批判C++过于臃肿和迷宫般的语法特性,摒弃了一大堆东西包括运算符重载。ThinkingInJava一书中好像有对此事的评价,从负面讲,运算符重载的滥用容易导致语义的混乱,例如apple+person就很难推测出其背后的意图。但是没有它,像复数类Complex的四则运算就显得十分繁琐。运算符重载到底是不是鸡肋呢?个人觉得运算符重载还是有很多用武之地的,尤其适用于和数值相关的场景。下面介绍一个我遇到的案例。

现在定义了一批0到1的数值:

复制代码
代码
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因噎废食而将运算符重载拒之门外。

posted @   dragonpig  阅读(1958)  评论(7编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示