Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# creating a custom "double" type

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
}
like image 249
neggenbe Avatar asked Jul 05 '16 08:07

neggenbe


People also ask

What C is used for?

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 in C language?

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.

What is the full name of C?

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.

Is C language easy?

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.


2 Answers

I'd suggest the following:

  1. Create a new struct, called MoneyAmount.
  2. It contains one field: A double.
  3. The constructor with one double parameter, this constructor rounds the value and assigns it to the internal field.
  4. Add the members/operators you might need to your struct so it has all the same operations as the double, like +, -, etc. But also casts/conversions from/to other types. Every operation produces a new instance of MoneyAmount with a rounded value.
  5. Also consider implementing the interfaces 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 --> int
  • Explicit MoneyAmount --> float
  • Explicit MoneyAmount --> double
  • Explicit MoneyAmount --> decimal

  • Implicit int--> MoneyAmount

  • Implicit float --> MoneyAmount
  • Implicit double--> MoneyAmount
  • Implicit decimal --> MoneyAmount

All mathematical operations you may want to implement:

  • MoneyAmount + MoneyAmount
  • MoneyAmount - MoneyAmount
  • MoneyAmount * MoneyAmount
  • MoneyAmount / MoneyAmount

All relational operations you may want to implement:

  • MoneyAmount == MoneyAmount
  • MoneyAmount != MoneyAmount
  • MoneyAmount > MoneyAmount
  • MoneyAmount >= MoneyAmount
  • MoneyAmount < MoneyAmount
  • MoneyAmount <= MoneyAmount

With all these operations your have all basics covered.

like image 151
Martin Mulder Avatar answered Sep 28 '22 02:09

Martin Mulder


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.

Mathematical & Logical Operation

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));
}

Explicit/Implicit casts

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)

like image 39
Jamiec Avatar answered Sep 28 '22 01:09

Jamiec