Home > Back-end >  Is it possible to use a class instance as a value in C#?
Is it possible to use a class instance as a value in C#?

Time:12-18

Consider this example,

public class NumberAsIs 
{
    public NumberAsIs(double number) { _number = number; }
    public double Value => _number;
    private double _number;
}

public class Percentage
{
    public Percentage(double number) { _number = number; }
    public double Value => _number * 0.01;
    private double _number;
}

class Program
{
    static void Main(string[] args)
    {
        var a = new NumberAsIs(1);
        var b = new Percentage(2);
        var c = a.Value   b.Value; // Expect c = 1.02
    }
}

Because the only purpose of NumberAsIs and Percentage is to call them for their Value method, is there a way to just call them as value types? For example,

class Program
{

    static void Main(string[] args)
    {
        var a = new NumberAsIs(1);
        var b = new Percentage(2);
        double c = a   b; // Expect c = 1.02
    }
}

I'm not looking to redefine the operator , but to access the numeric value just by calling the object. If it's not possible just fine and say no, asking just in case there is a workaround/sugar syntax I'm not aware of.

The question is roughly related to this other: Value type class definition in C#?

CodePudding user response:

You can try implementing implicit operator:

//TODO: better use struct, not class
public class NumberAsIs {
  ...
  public static implicit operator double(NumberAsIs value) => value.Value;
}

//TODO: better use struct, not class
public class Percentage {
  ...
  public static implicit operator double(Percentage value) => value.Value;
}

Now you can put

var a = new NumberAsIs(1);
var b = new Percentage(2);

// double c = 1.02 as expected
var c = a   b; 

// 0.98
var c2 = a - b;
// 0.02
var c3 = a * b;

CodePudding user response:

If you define both directions:

public class NumberAsIs
{
    private readonly double _number;
    private NumberAsIs(double d) => _number = d;

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

public class Percentage
{
    private readonly double _number;
    private Percentage(double d) => _number = d/100.0;

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

It means you can do this:

NumberAsIs a = 1;
Percentage b = 2;
var c = a   b; // Expect c = 1.02
Console.WriteLine(c); //prints 1.02

CodePudding user response:

I think what you want is to keep the value as defined, but convert it into a double using whatever conversion factor applies.

Here operations such as etc are handled by invoking the implicit conversion to double.

public struct Number 
{
    public Number(double value) : this()
    {
        Value = value;
    }
    public static implicit operator double(Number number)=>number.Value;
    public static implicit operator Number(double value) => new Number(value);
    public double Value { get; }
    public override string ToString() => $"{Value:g}";
}
public struct Percent
{
    public Percent(double value) : this()
    {
        Value = value;
    }
    public static implicit operator double(Percent number) => number.Value/100;
    public static implicit operator Percent(double value) => new Percent(value * 100);
    public double Value { get; }
    public override string ToString() => $"{Value:g}%";
}

static class Program
{
    static void Main(string[] args)
    {
        Number a = new Number(1.0);     // 1.0
        Percent b = new Percent(2.0);   // 2%
        double c = a   b;

        Console.WriteLine($"{a}   {b} = {c}");
        // 1   2% = 1.02
    }
}
  •  Tags:  
  • c#
  • Related