c#:创建只读属性的奇怪方式

本文关键字:方式 只读属性 创建 | 更新日期: 2023-09-27 18:08:12

我正在看《Head First c#》这本书,我不明白为什么他们用下面的方法来创建属性。这似乎与我在其他地方看到的惯例不一致,也与书本身不一致。

我理解创建属性的模式是:

    private int myVar;
    public int MyProperty
    {
        get { return myVar; }
        set { myVar = value; }
    }
根据上面的模式,我应该这样写我的代码:
    private decimal cost;
    public decimal Cost
    {
        get
        {   
            cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople; 
            if (HealthyOption)
            {
                cost *= .95M;
            }
            return cost;
        }
    }

在这本书中,它是这样呈现的:

    public decimal Cost
    {
        get
        {
            decimal totalCost = CalculateCostOfDecorations();
            totalCost += (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson)*NumberOfPeople;
            if (HealthyOption)
            {
                totalCost *= .95M;
            }
            return totalCost;
        }
    }

两个代码在程序中都工作得很好。创建此类属性的最佳实践是什么?十进制totalCost是否在属性私有中?如果是这样,为什么在创建属性之前不声明它呢?

还有,创建两行代码的意义是什么呢?

            decimal totalCost = CalculateCostOfDecorations();
            totalCost += (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson)*NumberOfPeople;

,而你可以通过写

来完成完全相同的事情
cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople;

c#:创建只读属性的奇怪方式

两个示例之间的主要区别是,正如您所注意到的,一个有支持字段(这就是将decimal cost放在属性定义之外的原因),而另一个没有。

第二个样本中的totalCost变量根本不是字段(private或其他),它只是get方法的局部变量。

都是可以的,但是如果您不使用任何backing字段,则没有必要使用它。至于你的第二个问题,我不知道为什么他们特别这样做,除了使变量声明更简单。

作为题外话,两个示例都有点偏离标准c#实践,因为对于属性getter来说,这是一个非常多的逻辑。

两种方式都可以。"如果你问哪一种方式最好,我会说两者都不是。

由于Cost实际上不是一个字段或属性(它是计算出来的东西,不能由调用者设置),因此将其实现为返回值的方法更为习惯。不需要任何成员变量。

public decimal GetCost()
{
    var cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople; 
    if (HealthyOption)
    {
        cost *= .95M;
    }
    return cost;
}

小数totalCost是私有属性吗?如果是这样,为什么呢在创建属性之前没有声明?

property内部创建以限制其作用域。如果将totalCost声明在property之上,则可以在整个class中访问它。

还有,创建两行代码的意义是什么呢?

通常,只是为了可读性。一行字很好,直到你必须不断滚动才能看到它的全部。

正如其他人所提到的,这两个字段都不是真正的c#习惯用法,但是为这两个字段设置支持字段可能会导致后面代码中的错误,例如:

private decimal cost;
public decimal Cost
{
    get
    {   
        cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople; 
        if (HealthyOption)
        {
            cost *= .95M;
        }
        return cost;
    }
}
public decimal CalculateDiscountedCost() {
     return cost * 0.75m; //Note the deliberate mistake?
}

通过(可能不小心)访问后续方法中的支持变量,而不是属性,您可以轻松地开发一些难以维护的代码。在这种情况下,折扣成本在调用时可能是正确的,但这取决于在调用CalculateDiscountedCost方法之前访问的公共属性Cost,以便设置支持变量。

由于后备变量基本上是不必要的,因此最好不要它。

totalCost变量不是private,它是getter内部的局部变量。该变量不存在于该方法之外,因此它只在get运行时占用内存。private cost字段将和类实例一样留在内存中。这个变量只能在getter中使用,所以它应该是getter中的一个局部变量。没有理由让它成为一个类字段。

创建两行的目的是为了在页面上容纳一行。代码是完全一样的;只是格式不同。

是的,基于计算的属性根本不需要私有字段来保存值(除非您希望缓存该值以避免在后续获取时重新计算)。事实上,一种更好的(至少更简洁、更容易遵循的)方法是根本不使用局部变量:

public decimal Cost
{
    get
    {
        return (CalculateCostOfDecorations() +
               (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson)
                 * NumberOfPeople) * HealthyOption? .95m: 1m; 
     }
}

实际上应该使用Get方法只返回私有变量的值,因为这是要遵循的良好实践。它将使您更容易维护其他可能使用私有变量'以防万一'的函数。

总是使用"setter "来改变变量的值,使用"getter "来不做任何改变地返回它。

我建议在像您这样的情况下(其中get和set只是返回或设置单个支持变量的值),您使用"自动"属性,例如:

public int MyProperty { get; set; }

并且,也许您不希望类的外部用户访问该setter:

public int MyProperty { get; private set; }