Head First C#:创建只读的奇怪方式 属性

Head First C#: strange way to create a read-only property

我正在阅读 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;
        }

    }

这两种代码在程序中都可以正常工作。创建此类属性的最佳做法是什么? decimal totalCost里面是属性private吗?如果是这样,为什么不在创建 属性 之前声明它呢?

此外,创建两行代码有什么意义:

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

当您可以通过编写来完成完全相同的事情时:

cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople;

Is the decimal totalCost inside the property private? If so, why is it not declared before creating the property instead?

它是在 property 内部创建的,以限制其范围。如果您在 property 之上声明了 totalCost,那么整个 class 本身都可以访问它。

Also, what is the point of creating two lines of code:

通常,只是为了便于阅读。一个衬垫很棒,直到您必须不断滚动才能看到它的全部内容。

这两个样本之间的主要区别在于,如您所见,一个样本有一个 支持字段 (这就是将 decimal cost 放在 属性 定义有)而另一个没有。

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

两者都很好,但如果您没有将支持字段用于任何事情,则没有必要。至于你的第二个问题,除了让变量声明更简单之外,我不知道他们为什么专门这样做。

顺便说一句,两个 示例都与标准 C# 实践有点不同,因为那是 属性 getter 的大量逻辑。

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

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

totalCost 变量不是 private,它是 getter 内部的局部变量。该变量不存在于该方法之外,因此它仅在获取 运行 时占用内存。只要 class 实例存在,您的 private cost 字段就会保留在内存中。该变量仅在 getter 内部使用,因此它应该是 getter 中的局部变量,如书中所示。它没有理由成为 class 字段。

创建两条线的目的是使其适合页面上的一条线。代码完全一样;它只是格式不同。

您实际上应该使用 Get 方法来仅 return 私有变量的值,因为这是 好的做法 跟随。这将使您更容易维护其他可能使用私有变量 'just in case'.

的函数

总是使用 "setters" 来改变变量的值,"getters" 只是 return 它没有任何变化。

正如其他人所提到的,这些都不是真正惯用的 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 方法之前访问 public 属性 Cost 以设置支持变量。

由于支持变量本质上是不必要的,所以最好不要它。

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

因为 Cost 不是真正的字段或 属性(它是计算出来的东西,不能由调用者设置),作为方法实现会更惯用其中returns一个值。不需要成员变量。

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

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

public int MyProperty { get; set; }

而且,也许您不希望 class 的外部用户访问 setter:

public int MyProperty { get; private set; }