Head First C #: Weird Way to Create a Read-Only Property

I am looking at the Head First C # book, and I cannot understand why they used the following method of creating a property. It just seems incompatible with the convention, which I see throughout the book itself.

I understand that the template for creating properties is:

private int myVar; public int MyProperty { get { return myVar; } set { myVar = value; } } 

Based on the above template, I would write my code as follows:

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

The book presents the following:

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

Both codes work fine in the program. What is the best practice for creating such properties? Is the decimal totalCost inside the private property? If so, why is it not declared before creating the property?

Also, what's the point of creating two lines of code:

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

when you can accomplish the same thing by writing:

 cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople; 
+6
source share
8 answers

The main difference between the two samples is, as you have noticed, that you have a support field (this is what puts the decimal cost outside the property definition) and the other does not.

The variable totalCost in the second example is not a field at all ( private or otherwise), it is just a variable local to the get method.

Both are good, although if you are not using the support field for anything, you really don't need to have one. As for your second question, I don’t know why they specifically did it this way, except to simplify the declaration of the variable.

As an aside, both examples are slightly different from standard C # practice, as this is terrible logic for the getter property.

+8
source

Both methods work. If you ask which way is better, I would also say.

Since Cost is actually not a field or property (this is what is calculated and cannot be set by the caller), it would be more idiomatic to implement it as a method that returns a value. No member variable required.

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

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

It is created inside the property to limit the scope. If you declared totalCost above the property , it will be available throughout the class tag.

Also, what's the point of creating two lines of code:

Usually, just for readability. One liner is gorgeous, until you have to scroll to see it in its entirety.

+3
source

As mentioned by others, none of them is really idiomatic C #, however, the presence of a support field for this can lead to errors later in the code, for example:

 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? } 

By (possibly randomly) accessing a helper variable in a subsequent method, rather than a property, you can easily develop some hard code to maintain. In this case, the discounted value may be correct when called, but will depend on the public ownership of the Cost Access is made before calling the CalculateDiscountedCost method in order to set the lining variables.

Since the base variable is essentially unnecessary, it would be better to do without it.

+2
source

The variable totalCost not private , it is a local variable inside the receiver. The variable does not exist outside this method, so it takes up only memory at startup time. Your private cost field will remain in memory until the class instance does this. This variable is used only inside the getter, so it should be local in the getter, as the book shows. There is no reason to be a class field for this.

The point of creating two lines is such that it can correspond to one line on a page. The code is exactly the same; It is simply formatted differently.

+1
source

yes, computational-based properties do not require the private field to retain a value at all (unless you want to cache the value to avoid recalculation on subsequent acquisitions). actually even better (at least easier and easier to follow) is to do this without any local variables:

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

In fact, you should use the Get method only to return the value of the private variable, as this is good practice. This will make it easier for you to work with other functions that may use the private "just in case" variable.

Always use β€œsetters” to change the value of the β€œgetters” variable to simply return it without any change.

0
source

I would like to assume that in cases where you have (where to get and set to only return or set the value of one variable of the substrate), you use "automatic" properties, such as this:

 public int MyProperty { get; set; } 

And perhaps you do not want external users of this class to have access to this device:

 public int MyProperty { get; private set; } 
0
source

All Articles