I have a lot of classes that have numeric values that are configurable by the customer during runtime and should be clamped between a min and a maximum value. The value changes should also be logged. An example of this is given below:
public class MyClass 
{
    public double AMin { get; set; }
    public double AMax { get; set; }
    public double A { get; private set; }
    public double BMin { get; set; }
    public double BMax { get; set; }
    public double B { get; private set; }
    public double CMin { get; set; }
    public double CMax { get; set; }
    public double C { get; private set; }
    public bool SetA(double value) 
    {
        double clamped = Clamp(value, AMin, AMax);
        if (clamped != value) 
        {
            LogError("New value: {value} for A is out of range.");
            return false;
        }
        else 
        {
            LogError("Set A to: {value}.");
            return true;
        }
    }
    public bool SetB(double value) 
    {
        double clamped = Clamp(value, BMin, BMax);
        if (clamped != value) 
        {
            LogError("New value: {value} for B is out of range.");
            return false;
        }
        else 
        {
            LogError("Set B to: {value}.");
            return true;
        }
    }
    public bool SetC(double value) 
    {
        double clamped = Clamp(value, CMin, CMax);
        if (clamped != value) 
        {
            LogError("New value: {value} for C is out of range.");
            return false;
        }
        else 
        {
            LogError("Set C to: {value}.");
            return true;
        }
    }
    public static double Clamp(double value, double min, double max) 
    {
        if (value <= min) 
        {
            _value = min;
            return;
        }
        if (value >= max) 
        {
            _value = max;
            return;
        }
        _value = value;
    }
}
As the number of values grow, you can see this has me writing boilerplate code and it's easy to make copy/paste errors. I could make a Visual Studio snippet for this, but I was wondering if it would be a good solution if I would refactor this repetition into a class, so that it would look like below:
public class MyClass 
{
    public Parameter A { get; init; } = new Parameter("A");
    public Parameter B { get; init; } = new Parameter("B");
    public Parameter C { get; init; } = new Parameter("C"); 
    ...
}
public class Parameter 
{
    public string Name { get; set; } = "";
    public double Min { get; set; } = double.MinValue;
    public double Max { get; set; } = double.MaxValue;
    public double Value { get => _value; }
    private double _value = 0.0;
    public Parameter(string name) 
    {
        Name = name;
    }
    public double GetValue() 
    {
        return _value;
    }
    // returns true on success
    public bool SetValue(double value) 
    {
        if (value <= Min) 
        {
            _value = Min;
            Log.Error($"New value: {value} for {Name} too low.");
            return false;
        }
        if (value >= Max) 
        {
            _value = Max;
            Log.Error($"New value: {value} for {Name} too high.");
            return false;
        }
        Log.Info($"Set {Name} to: {value}.");
        _value = value;
    }    
}
Although this would have me writing MyInstance.MyParameter.Value instead of MyInstance.MyParameter all the time, and it "violates" the law of Demeter, I think in the end it will save me a lot of time and I think it would be more maintainable.
Is it a common practice to do something like this, or is there a big downside that I am not yet seeing?
Side-note: I work in industrial automation, more specific with PLCs, so validation using exceptions is not an option for me. I have a C# background, hence the example is given in that language.



GetValuemethod is redundant to the getter of your pre-existingValueproperty