在另一个属性设置器中使用属性值

本文关键字:属性 另一个 设置 | 更新日期: 2023-09-27 18:16:55

在我的Class中,我需要根据另一个值设置一个property值:

public class Quantities
{
    private int _quant;
    public int Quant
    {
        get { return _quant; }
        set
        {
            if (Unit == "K")
            {
                _quant = value / 1000;
            }
            else
            {
                _quant = value;
            }
        }
    }
    public string Unit { get; set; }
}

根据几次测试,我让它运行良好,但我仍然不知道这样做是否安全
是否可能在Unit Property之前对Quant Property进行求值,或者编译器(或JIT(是否知道应该首先分配Unit Property

在另一个属性设置器中使用属性值

这与编译器或JIT无关您的代码分配值需要知道分配它们的顺序。

BTW:您的代码显示出时间耦合。最好通过使属性readonly和提供一个需要单位的构造函数:来至少使Unit不可更改

public class Quantities
{
    private readonly string _unit;
    private int _quant;
    public Quantities(string unit)
    {
        if(unit == null) throw new ArgumentNullException("unit");
        _unit = unit;
    }
    public int Quant
    {
        get { return _quant; }
        set
        {
            if (Unit == "K")
            {
                _quant = value / 1000;
            }
            else
            {
                _quant = value;
            }
        }
    }
    public string Unit { get { return _unit; } }
}

现在不能以错误的方式使用此类。

关于更多可以在课堂上提高的分数,请参考Lasse的回答。

此类外部的代码必须知道此依赖关系,否则可能会有人在不重新设置Quant:的情况下更改Unit

var x = new Quantities(); // why no constructor for this?
x.Unit = "K";
x.Quant = 1700;           // why int? this will now be 1, not 1.7
x.Unit = "M";

就我个人而言我会将类作为一个结构,并使其不可变:

public struct Quantity
{
    private readonly double _Value;
    private readonly string _Unit;
    public Quantity(double value, string unit)
    {
        _Value = value;
        _Unit = unit;
    }
    public double Value
    {
        {
            return _Value;
        }
    }
    public double Unit
    {
        {
            return _Unit;
        }
    }
}

还请注意,我根本没有更改值,因此:

var x = new Quantity(1700, "K");

意思是17000,而不是1.7K。我不会对数据进行这种"自动魔法"解释。如果你需要用不同的单位显示值,我会构建一个转换系统:

    public Quantity ConvertToUnit(string newUnit)
    {
        var newValue = ... calculate value with new unit
        return new Quantity(newValue, newUnit);
    }

这个类不是一个好的设计。不要这样做。

考虑以下代码:

Quantities q1 = new Quantities { Unit = "K", Quant = 1000};
Console.WriteLine(q1.Quant); // Prints 1
// Make a copy of q1
Quantities q2 = new Quantities{ Unit = q1.Unit, Quant = q1.Quant };
Console.WriteLine(q2.Quant); // Prints 0

你可能会认为,制作一份工程量的副本可以通过做一份像上面这样的基本副本来完成。它并没有向你展示这种设计有多危险

在对上面接受的答案进行更改后,这仍然是一个问题

如果您使用Daniel建议的更改,那么您仍然有与属性setter和getter不可交换相关的问题。当然,您将被迫将单元传递到构造函数中,但对象副本仍然不能像用户预期的那样工作:

Quantities q1 = new Quantities("K"){ Quant = 1000};
Console.WriteLine(q1.Quant); // Prints 1
// Make a copy of q1
Quantities q2 = new Quantities(q1.Unit){ Quant = q1.Quant };
Console.WriteLine(q2.Quant); // STILL Prints 0