【发布时间】:2016-11-07 00:19:37
【问题描述】:
在我的应用程序中,我希望我所有存储金额的属性都舍入到 n 小数位。
为了代码清晰,我宁愿有一个自定义类型MoneyAmount,我的所有相应字段都会有,而不是必须在所有属性获取器/设置器中放置一个“Math.Round(value, n)”。
有没有一种巧妙的方法来实现这一点?
我看到 this post 关于重载赋值运算符 - 这是建议的方法吗?
编辑: 鉴于多个视图,我在这里发布我导出的完整代码:
public struct MoneyAmount {
const int N = 4;
private readonly double _value;
public MoneyAmount(double value) {
_value = Math.Round(value, N);
}
#region mathematical operators
public static MoneyAmount operator +(MoneyAmount d1, MoneyAmount d2) {
return new MoneyAmount(d1._value + d2._value);
}
public static MoneyAmount operator -(MoneyAmount d1, MoneyAmount d2) {
return new MoneyAmount(d1._value - d2._value);
}
public static MoneyAmount operator *(MoneyAmount d1, MoneyAmount d2) {
return new MoneyAmount(d1._value * d2._value);
}
public static MoneyAmount operator /(MoneyAmount d1, MoneyAmount d2) {
return new MoneyAmount(d1._value / d2._value);
}
#endregion
#region logical operators
public static bool operator ==(MoneyAmount d1, MoneyAmount d2) {
return d1._value == d2._value;
}
public static bool operator !=(MoneyAmount d1, MoneyAmount d2) {
return d1._value != d2._value;
}
public static bool operator >(MoneyAmount d1, MoneyAmount d2) {
return d1._value > d2._value;
}
public static bool operator >=(MoneyAmount d1, MoneyAmount d2) {
return d1._value >= d2._value;
}
public static bool operator <(MoneyAmount d1, MoneyAmount d2) {
return d1._value < d2._value;
}
public static bool operator <=(MoneyAmount d1, MoneyAmount d2) {
return d1._value <= d2._value;
}
#endregion
#region Implicit conversions
/// <summary>
/// Implicit conversion from int to MoneyAmount.
/// Implicit: No cast operator is required.
/// </summary>
public static implicit operator MoneyAmount(int value) {
return new MoneyAmount(value);
}
/// <summary>
/// Implicit conversion from float to MoneyAmount.
/// Implicit: No cast operator is required.
/// </summary>
public static implicit operator MoneyAmount(float value) {
return new MoneyAmount(value);
}
/// <summary>
/// Implicit conversion from double to MoneyAmount.
/// Implicit: No cast operator is required.
/// </summary>
public static implicit operator MoneyAmount(double value) {
return new MoneyAmount(value);
}
/// <summary>
/// Implicit conversion from decimal to MoneyAmount.
/// Implicit: No cast operator is required.
/// </summary>
public static implicit operator MoneyAmount(decimal value) {
return new MoneyAmount(Convert.ToDouble(value));
}
#endregion
#region Explicit conversions
/// <summary>
/// Explicit conversion from MoneyAmount to int.
/// Explicit: A cast operator is required.
/// </summary>
public static explicit operator int(MoneyAmount value) {
return (int)value._value;
}
/// <summary>
/// Explicit conversion from MoneyAmount to float.
/// Explicit: A cast operator is required.
/// </summary>
public static explicit operator float(MoneyAmount value) {
return (float)value._value;
}
/// <summary>
/// Explicit conversion from MoneyAmount to double.
/// Explicit: A cast operator is required.
/// </summary>
public static explicit operator double(MoneyAmount value) {
return (double)value._value;
}
/// <summary>
/// Explicit conversion from MoneyAmount to decimal.
/// Explicit: A cast operator is required.
/// </summary>
public static explicit operator decimal(MoneyAmount value) {
return Convert.ToDecimal(value._value);
}
#endregion
}
【问题讨论】:
-
旁注:使用 money 时,
decimal是更好的包装类型 -
存储时四舍五入似乎很可疑。通常你只会在显示时四舍五入。
-
@MatthewWatson 不,它不是,实际上每种货币的小数位数是严格定义的。 OP实际上是在询问Money Pattern
-
@PanagiotisKanavos 如果您要四舍五入到最接近的货币单位,它会变得比仅存储 N 个小数位更复杂。例如,如果您想将金额拆分为 30%/70%,并且计算不会产生两个精确到 N 位小数的值,则必须确保在四舍五入后,这两个拆分值仍然相加正是原始值。除了简单的四舍五入到 N 位之外,这还需要额外的工作。
-
@MatthewWatson 我知道,这就是为什么
Money是一种模式。事实上,它甚至更复杂,因为有一些规则可以处理最小化舍入误差(银行家的舍入算法只是一种技术)和分配丢失的美分,以便什么都不做迷路。其他管理货币转换的规则,其他管理允许每种货币的小数位数以及内部计算的小数位数