Home > Enterprise >  C# Class with dependent properties
C# Class with dependent properties

Time:10-17

I'm very new to C# programming, and I'm currently struggling with what should be (I think) a piece of cake code for experienced programmers. I want to write a very little app to calculate a tax (21%) on a number:

  • If I define an exclVAT number, it should return the calculated inclVAT number
  • If I define an inclVAT number, it should return the calculated exclVAT number

My goal is to have something like this: an app that gives the results as soon as you type a value in one of the two boxes:

VAT utility (This will be done in WPF using XAML, with an INotifyPropertyChanged interface, but this is not the goal of my question).

I'm trying to do this with 1 class, and 2 properties: inclVat and exclVat (both as type double). But the tricky thing is that both properties depend on each other. So if I set/change the exclVat property to 100, I want to have the inclVat property to be changed to 121. And if I set/change the inclVat value to 100, I want the exclVat property changed to 0,83.

I already come up with this code, but is is not sufficient, as the public property fields don't change when I change the values on them...

The Class:

public class Vat
    {

        private double _inclVat;

        public double InclVat
        {
            get 
            {
                if (_ExclVat == 0)
                {
                    return _inclVat;
                }
                else
                {
                    return (_ExclVat * 1.21);
                }
                
            }
            set
            {
                _inclVat = value;
            }
        }

        private double _ExclVat;

        public double ExclVat
        {
            get 
            {
                    return System.Math.Round(_inclVat / 1.21, 2);
            }
            set
            {
                _ExclVat = value;
                
            }
        }
    }

And when I run it with some assignments:

Vat Number = new Vat();
Number.InclVat = 100;

System.Console.WriteLine($"InclVat: {Number.InclVat}");
System.Console.WriteLine($"ExclVat: {Number.ExclVat}");

System.Console.WriteLine("Changing inclVat to 200");
Number.InclVat = 200;

System.Console.WriteLine($"InclVat: {Number.InclVat}");
System.Console.WriteLine($"ExclVat: {Number.ExclVat}");

System.Console.WriteLine("Changing exclVat to 100");
Number.ExclVat = 100;

System.Console.WriteLine($"InclVat: {Number.InclVat}");
System.Console.WriteLine($"ExclVat: {Number.ExclVat}");

I have the following output:

InclVat: 100
ExclVat: 82,64
Changing inclVat to 200
InclVat: 200
ExclVat: 165,29
Changing exclVat to 100
InclVat: 121
ExclVat: 165,29

In the beginning it's ok, but as soon as I change the exclVat property, the output isn't ok anymore (last 2 lines). Can anyone help me with this?

CodePudding user response:

You can put something like this:

  public class Vat {
    private decimal m_IncludeVat; // <- decimal is a better choice for finance

    // To compute VAT we should know the percent; let it be known
    public const decimal Percent = 18.0m;

    public decimal IncludeVat {
      get => m_IncludeVat;
      set {
        // negative cash are usually invalid; if it's not the case, drop this check
        if (value < 0)
          throw new ArgumentOutOfRangeException(nameof(value));

        m_IncludeVat = value;
        Tax = Math.Round(m_IncludeVat / 100 * Percent, 2);
      }   
    }

    public decimal ExcludeVat {
      get => m_IncludeVat - Tax;
      set {
        if (value < 0)
          throw new ArgumentOutOfRangeException(nameof(value));

        m_IncludeVat = Math.Round(value / (100 - Percent) * 100, 2);
        Tax = m_IncludeVat - value; 
      }   
    }

    // Let's be nice and provide Tax value as well as IncludeVat, ExcludeVat 
    public decimal Tax {get; private set;}

    public override string ToString() =>
      $"Include: {IncludeVat:f2}; exclude: {ExcludeVat:f2} (tax: {Tax:f2})";
  }

Let's add some tests:

  (decimal cash, bool isInclude)[] tests = new (decimal cash, bool isInclude)[] {
    (100, true),
    (200, true),
    (100, false),
    (121.95m, true)  
  };

  var report = string.Join(Environment.NewLine, tests
    .Select(test => {
      Vat num = new Vat();

      if (test.isInclude)
        num.IncludeVat = test.cash;
      else
        num.ExcludeVat = test.cash;

      return num;
    }));

  Console.WriteLine(report);

Outcome:

Include: 100,00; exclude: 82,00 (tax: 18,00)
Include: 200,00; exclude: 164,00 (tax: 36,00)
Include: 121,95; exclude: 100,00 (tax: 21,95)
Include: 121,95; exclude: 100,00 (tax: 21,95)

CodePudding user response:

it seems like you want the computed value of InclVat [the public property], not the backing field _inclVat when you are getting ExclVat. Try changing ExclVal's get to

 return System.Math.Round(InclVat / 1.21, 2);
  • Related