In my application I want all my properties storing money amounts to be rounded to n
decimal places.
For code clarity, I'd rather have a custom type MoneyAmount
which all my corresponding fields would have, instead of having to put a `Math.Round(value, n)' in all the property getters/setters.
Is there a neat way to achieve this?
I saw this post about overloading assignment operators - is this the suggested approach?
EDIT: Given the multiple views, I post the full code I derived here:
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
}
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
I'd suggest the following:
double
.double
parameter, this constructor rounds the value and assigns it to the internal field.double
, like +, -, etc. But also casts/conversions from/to other types. Every operation produces a new instance of MoneyAmount with a rounded value.IFormattable
, IComparable
and IConvertible
.Short example:
public struct MoneyAmount
{
const int N = 4;
private readonly double _value;
public MoneyAmount(double value)
{
_value = Math.Round(value, N);
}
// Example of one member of double:
public static MoneyAmount operator *(MoneyAmount d1, MoneyAmount d2)
{
return new MoneyAmount(d1._value * d2._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>
/// Explicit conversion from MoneyAmount to double.
/// Explicit: A cast operator is required.
/// </summary>
public static explicit operator double(MoneyAmount value)
{
return value._value;
}
/// <summary>
/// Explicit conversion from MoneyAmount to int.
/// Explicit: A cast operator is required.
/// </summary>
public static explicit operator MoneyAmount(int value)
{
return new MoneyAmount(value);
}
/// <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;
}
// All other members here...
}
I realize: The double
has a lot of members...
With these operators, the following code is possible:
MoneyAmount m = 1.50; // Assignment from a double.
MoneyAmount n = 10; // Assignment from an integer.
m += n; // Mathematical operation with another MoneyAmount .
m *= 10; // Mathematical operation with an integer.
m -= 12.50; // Mathematical operation with a double.
EDIT
All conversion methods you may want to implement:
Explicit MoneyAmount --> decimal
Implicit int--> MoneyAmount
All mathematical operations you may want to implement:
All relational operations you may want to implement:
With all these operations your have all basics covered.
This gets big very quickly. Writing a struct is easy, as demonstrated in @MartinMulder's answer, but consider that you will want to overload a number of combinations of operators, as well as including a few implicit/explicit casts as well.
Consider that you may want to do mathematical operations on MoneyAmount
MoneyAmount
+ MoneyAmount
MoneyAmount
+ double
MoneyAmount
+ int
MoneyAmount
+ decimal
That is 4 overloads of the +
operator. Rinse and repeat for -
,/
,*
(and possibly %
). You'll also want to overload <
,<=
, ==
and >
, >=
. Thats something like 30 operator overloads. Phew! Thats a lot of static methods.
public static MoneyAmount operator +(MoneyAmount d1, double d2)
{
return new MoneyAmount((decimal)(d1._value + d2));
}
Now consider that instead of this code
MoneyAmount m = new MoneyAmount(1.234);
You wanted to do this:
MoneyAmount m = 1.234;
That can be achieved with an implicit cast operator.
public static implicit operator MoneyAmount(double d)
{
return new MoneyAmount((decimal)d);
}
(You'll need one for every type you want to allow implicit casts)
Another one:
int i = 4;
MoneyAmount m = (MoneyAmount)i;
This is done with an explicit cast operator overload.
public static explicit operator MoneyAmount(double d)
{
return new MoneyAmount((decimal)d);
}
(Again, 1 for every type you want to allow explicit casts)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With