1

I am trying to create a new type UInt24. In order to do so, I am using a struct (any better suggestion would be welcome).
While I am now able to cast a variable to this new defined type, I am unable to support generic arithmetic.
I have tried a bunch of things with explicit and implicit operators, but I do not really get how that works.
Here is what I have:

namespace MySytem
{    
    public struct UInt24
    {
        internal uint m_value;

        public static explicit operator UInt24(uint v) => new UInt24(v);

        public const uint MaxValue = (uint)0xFFFFFF;
        public const short MinValue = unchecked((short)0x000000);

        public UInt24(uint v)
        {
            if (v > MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(v), $"Value too big - Max is {MaxValue}.");
            }
            if (v < MinValue)
            {
                throw new ArgumentOutOfRangeException(nameof(v), $"Value too small - Min is {MinValue}.");
            }

            this.m_value = v;
        }
    }
}

Now, this allows me to do things like this:

UInt24 a = (UInt24)0x123456;

But I would like to do be able to do this:

UInt24 a = (UInt24)0x123456;
a++;       // Not working
a--;       // Not working
a = a + 1  // Not working

Also, is there a way to be able to declare a UInt24 variable without having to cast the number? Instead of:

UInt24 a = (UInt24)0x123456;

Could we get that to work directly:

UInt24 a = 0x123456;    // No casting needed
stackMeUp
  • 522
  • 4
  • 16
  • 3
    You need to implement the arithmetic operators ++, --, + and -. Also, to enable an implicit cast, define your operator `implicit`. In that case, you should be able to assign directly to UInt24: `UInt24 u24 = 1234;` – Oguz Ozgul May 14 '20 at 08:52
  • @OguzOzgul, thanks. Yes indeed, it works with implicit :-) I cannot figure out how to implement the ++, -- thing though. Would you have any example to share? – stackMeUp May 14 '20 at 08:55

1 Answers1

1

You can define your operator implicit:

public static implicit operator UInt24(uint v) { return new UInt24(v); }

You need to implement +, -, ++, and -- operators:

public static UInt24 operator +(UInt24 u1, UInt24 u2) { return u1.m_value + u2.m_value; }
public static UInt24 operator -(UInt24 u1, UInt24 u2) { return u1.m_value - u2.m_value; }
public static UInt24 operator ++(UInt24 u1) { return u1.m_value + 1; }
public static UInt24 operator --(UInt24 u1) { return u1.m_value - 1; }

Then can execute arithmetic operations:

UInt24 u24_1 = 0x000001;
UInt24 u24_2 = u24_1 + 0x000001;
u24_1++;
u24_2--;
Console.WriteLine("{0}", u24_1);
Console.WriteLine("{0}", u24_2);

Also recommended is overriding ToString():

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

The results are,

2
1
Oguz Ozgul
  • 6,809
  • 1
  • 14
  • 26
  • Oh man, that is awesome! Thanks! I thought I had to use implicit/explicit, but I see you did not use that to implement the ++/--. – stackMeUp May 14 '20 at 09:07
  • Just a small question. Will that handle overflow or do I need to handle it in each individual arithmetic implementation? – stackMeUp May 14 '20 at 09:13
  • 1
    I think yes, because every arithmetic operation will end up in your struct constructor. `return u1.m_value + 1` for example will be implicitly cast to UInt24 which is instantiated through your constructor, which checks for overflow. – Oguz Ozgul May 14 '20 at 10:35
  • That is what I suspected, thank you for the confirmation :-) – stackMeUp May 14 '20 at 11:24