.Net Single Digit Type

Is there a data type that I can use to store one digit, but nothing else. that is, one of 0 - 9 and nothing else.

I know that I could use short

, int

or long

, but this is for api design and I want to be sure that the user only has to give me one number.

+3


source to share


5 answers


Sounds like a good candidate for an enum type .

public enum Digit
{
    Zero, 
    One,
    Two,
    Three, 
    Four, 
    Five, 
    Six,
    Seven,
    Eight, 
    Nine
}

      

Benefits:



  • Easy to understand.
  • Converts directly to and from its base type

Inconvenience:

  • It is theoretically possible to create instances that are not in the range [0-9], since an enum instance can take on any value of the base type.
+4


source


There are several ways that you could go.

  • Create your own value type
  • Use an enum - it seems silly to enumerate from 0 to 9, although
  • Just use short text and throw an exception if it's too big ...


I think the latter will be the clearest from an API point of view. I would only create a new type if it will be used frequently throughout a large and complex API.

using System;
public class MyClass {
    public static void Main() {
        var test = new ApiClass();
        test.MyNum = 0; // OK
        test.MyNum = 1; // OK
        test.MyNum = 9; // OK

        test.MyNum = 10; // exception
        test.MyNum = -1; // exception
    }   
}

public class ApiClass {
    private short _myNum;
    public short MyNum {
        get {
            return _myNum;
        }
        set {
            if (value < 0 || value > 9)
                throw new ArgumentOutOfRangeException("Value must be between 0 and 9!");

            _myNum = value;
        }
    }
}

      

+4


source


Something like that?

struct SingleDigit
{
    readonly byte singleDigit;

    public SingleDigit() 
    {
        singleDigit = 0;
    }

    public SingleDigit(byte value)
    {
        // NOTE: it not a good practice to throw in a ctor
        if(value < 0 || value > 9)
            throw new ArgumenException();

        singleDigit = value;
    }

    // explicit byte to digit conversion operator
    public static explicit operator SingleDigit(byte b)  
    {
        Digit d = new SingleDigit(b);  // explicit conversion
        return d;
    }

    // explicit byte to digit conversion operator
    public static explicit operator SingleDigit(int b)  
    {
        Digit d = new SingleDigit((byte) b);  // explicit conversion
        return d;
    }

    // implicit digit to byte conversion operator
    public static implicit operator byte(SingleDigit digit)  
    {
        return digit.singleDigit;
    }

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

}

      

I added implicit (for lossless conversion) and explicit casting operators so you can use it as if it were a normal type, for example:

// explicit (possible loss)
SingleDigit digit = (SingleDigit) 9;

// implicit conversion (lossless)
int convertedDigit = digit;

      

Benefits:

  • Easy to use
  • Works and feels like any other base type like byte, char, int
  • Can be easily extended with IConverter

    etc. to behave like standard types

Disadvantages:

  • A bit more creation and maintenance work than just listing
  • It can be more difficult to make it as strong and stable as existing types.
+2


source


No, there is no .Net type available with this capability. It's pretty straight forward to create though

public sealed class OneDigit {  
  public static readonly OneDigit One = new OneDigit(1);
  public static readonly OneDigit Two = new OneDigit(2);
  public static readonly OneDigit Three = new OneDigit(3);
  public static readonly OneDigit Four = new OneDigit(4);
  public static readonly OneDigit Five = new OneDigit(5);
  public static readonly OneDigit Six = new OneDigit(6);
  public static readonly OneDigit Seven = new OneDigit(7);  
  public static readonly OneDigit Eight = new OneDigit(8);
  public static readonly OneDigit Nine = new OneDigit(9);

  private readonly int _value;
  public int Value {
    get { return _value; }
  }

  private OneDigit(int value) {
    _value = value;
  }

  public static bool TryCreate(int value, out OneDigit digit) {
    if (value >=0 && value <= 9) {
      digit = new OneDigit(value);
      return true;
    }
    digit = null;
    return false;
  }
}

      

0


source


I would probably just put in a suitable parameter / member name and check as usual. IMO defining a custom type is overkill.

But if you want to go to a custom type route, I would define the structure like this:

public struct DecimalDigit
{
    readonly byte _value;

    public DecimalDigit(int value)
    {
        if(value<0||value>9)
            throw new ArgumentException("value", "value must be between 0 and 9");
        _value = (byte)value;
    }

    public byte Value 
    {
        get 
        {
            return _value;
        }
    }

    public static explicit operator DecimalDigit(int i)  
    {
        return new DecimalDigit(i);
    }

    public static implicit operator byte(DecimalDigit digit)  
    {
        return digit.Value;
    }
}

      

Plus multiple interface implementations ( IEquatable<Digit>

, IComparer<Digit>

, IConvertible

), a comparison of equations, ToString()

... which I missed here. With them, it becomes quite a bit of code for a small win.

0


source







All Articles