简体   繁体   中英

Type safety in C# using custom ValueType

In my code I have variables of type System.Double that either represent a quantity or a quantityDifference . In order to make my code safer, I would like to pass in a value of either type Quantity or QuantityDelta rather than double (to avoid passing in the the wrong value).

I can create a struct or class with a Value property or field but then I have to allocate memory for it and use the .Value syntax to use it:

public class Quantity
{
   public Quantity(double value) { Value = value; }
   public double Value;
}

and

var difference = new Quantity(differenceValue);
var used = difference.Value;

Is there a way to create a custom value type for this purpose, so the code reads like

Quantity difference = differenceValue;
var used = difference

Use the implicit operator .

public struct Quantity
{
    private readonly double value;

    public Quantity(double value) { this.value = value; }
    public double Value => value;

    public static implicit operator double(Quantity value) => value.value;
    public static implicit operator Quantity(double value) => new Quantity(value);
}

Also, since you are simply wrapping a value type, it would be best to use a struct rather than a class .

Operator overloading will help with Quantity difference = differenceValue; , specifically an implicit conversion operator for converting a double value into a Quantity struct instance.

However, nothing will help you with convincing the compiler to choose the double type for the var-declared used variable in var used = difference . Because var instructs the compiler to use the type of the right-hand expression as the type for the var-declared variable used . Which is Quantity here. Ie, the compiler will understand var used = difference as Quantity used = difference .

This is a quick sample I created for a Quantity struct that has basic operations of Addition, Subtraction, Multiplication, and Division.

public readonly struct Quantity
{
    private readonly double num;

    public Quantity(double number)
    {
        num = number;
    }

    public static Quantity operator +(Quantity a, Quantity b) => new Quantity(a.num + b.num);
    public static Quantity operator -(Quantity a, Quantity b) => new Quantity(a.num - b.num);
    public static Quantity operator *(Quantity a, Quantity b) => new Quantity(a.num * b.num);
    public static Quantity operator /(Quantity a, Quantity b)
    {
        if (b.num == 0)
        {
            throw new DivideByZeroException();
        }

        return new Quantity(a.num / b.num);
    }

    public override string ToString() => $"{num}";
}

A few quick test cases

var a = new Quantity(5);
var b = new Quantity(2);
Debug.WriteLine(a + b);  // output: 7
Debug.WriteLine(a - b);  // output: 3
Debug.WriteLine(a * b);  // output: 10
Debug.WriteLine(a / b);  // output: 2.5

If you do want the difference returned in a type called QuantityDelta you could replace the - operator above with:

public static QuantityDelta operator -(Quantity a, Quantity b) => new QuantityDelta(a.num - b.num);

And, add a new QuantityDelta struct as per:

public readonly struct QuantityDelta
{
    private readonly double num;

    public QuantityDelta(double number)
    {
        num = number;
    }

    public override string ToString() => $"{num}";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM