.Net Single Digit Type
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.
source to share
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;
}
}
}
source to share
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.
source to share
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;
}
}
source to share
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.
source to share