Search code examples
c#implicit-conversion

Understanding static implicit operator the right way


I had a brilliant thought, that does not seem to be so brilliant afterwards, but maybe I don't understand the whole thing correctly.

I have a class, that stores some numbers. Some other functions/methods need int's and some need double's. So I thought I can create a class with a precision conversion implicitly.

public class PreciseInteger
{
    public double PreciseValue {get; private set;}
    public int RoundedValue {get; private set;}

    public PreciseInteger(double value)
    {
        PreciseValue = value;
        RoundedValue = (int)Math.Round(value, 0, MidpointRounding.AwayFromZero);
    }

    public static implicit operator PreciseInteger(int number)
    {
        return new PreciseInteger(number);
    }

    public static implicit operator PreciseInteger(double number)
    {
        return new PreciseInteger(number);
    }

    public static implicit operator int(PreciseInteger number)
    {
        return number.RoundedValue;
    }

    public static implicit operator double(PreciseInteger number)
    {
        return number.PreciseValue;
    }

    public override string ToString()
    {
        return PreciseValue.ToString();
    }
}

And the class that uses this class is really a simple property storing class that does not much. So now I use somthing like

double myValue = myClass.StoredValue1 / myDivider;

But here I only get the integer value. I don't want to use an explicit casting (like Convert.ToDouble or (double)). So how could I make sure that the precise value is used and not the rounded one? Or did I misunderstand the whole concept and that doesn't work at all and I would have to use something like MyClass.MyDouble and MyClass.MyInteger values?

Edit: Ok, if I first say int newInt = myClass.StoredValue1 I get a rounded integer and if I use double newDouble = myClass.StoredValue1 I get the precise floating point number. But isn't there a way to say that one of them is always preferred?


Solution

  • The / operator is defined for both int and double:

    double operator /(double x, double y);
    int operator /(int x, int y);
    

    These two overloads are both applicable when you do:

    // assuming myClass.StoredValue1 and myDivider are PreciseIntegers
    double myValue = myClass.StoredValue1 / myDivider;
    

    because you defined an implicit conversion to int and an implicit conversion to double. However, the / that takes ints is actually a better function member, because int is a better conversion target, so the compiler always chooses the second overload.

    One way to work around this is to define your own / operator for PreciseInteger:

    public static PreciseInteger operator /(PreciseInteger number1, PreciseInteger number2) {
        return number1.PreciseValue / number2.PreciseValue;
    }
    

    Then you can do:

    double myValue = myClass.StoredValue1 / myDivider;