Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am going through the Head First C# book and I can't figure out why they used the following way to create a property. It just seems inconsistent with the convention I'm seeing everywhere else and in the book itself too.

I understand that the pattern for creating properties is:

    private int myVar;

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

Based on the above pattern I would have written my code like this:

    private decimal cost;

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

            return cost;
        }

    }

In the book it is presented like the following:

    public decimal Cost
    {
        get
        {
            decimal totalCost = CalculateCostOfDecorations();
            totalCost += (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson)*NumberOfPeople;

            if (HealthyOption)
            {
                totalCost *= .95M;
            }
            return totalCost;
        }

    }

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

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

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

when you can accomplish the exact same thing by writing:

cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople;
like image 530
alegz Avatar asked Aug 14 '15 20:08

alegz


People also ask

Is Head First C for beginners?

Good book for beginners. I have enjoyed reading through this and have learnt a lot.

Is head first CA a good book?

It is the best Go book for beginners, period. The Head First C book is said to be equally excellent. So these books are not only “effective”, but usually the #1 educational books for beginners.

Is Head First Java still relevant?

There is no doubt that Head First Java 3rd edition is now the best book to learn Java Programming in 2022. It's latest edition covers Java 17 and the latest features from recent Java releases, particularly Java 8 features, but it's still a great book to learn Java for complete beginners.

Where can I buy Head First books?

Amazon.com: Head First Series: Books.


5 Answers

The primary difference between the two samples is, as you have noticed, that one has a backing field (which is what putting decimal cost outside the property definition does) and the other doesn't.

The totalCost variable in the second sample isn't a field at all (private or otherwise), it is simply a variable local to the get method.

Both are fine, though if you aren't using the backing field for anything, its not really necessary to have. As to your second question, I have no idea why they specifically did it that way, other than to make the variable declaration simpler.

As an aside, both samples are a bit off from standard C# practice, as thats an awful lot of logic for a property getter.

like image 172
BradleyDotNET Avatar answered Oct 16 '22 19:10

BradleyDotNET


Both ways "work." If you're asking which way is best, I'd say neither.

Since Cost isn't really a field or property (it is something that is computed, and cannot be set by the caller), it would be more idiomatic to implement as a method which returns a value. No member variable should be needed.

public decimal GetCost()
{
    var cost = CalculateCostOfDecorations() + (CalculateCostOfBeveragesPerPerson() + CostOfFoodPerPerson) * NumberOfPeople; 
    if (HealthyOption)
    {
        cost *= .95M;
    }
    return cost;
}
like image 4
John Wu Avatar answered Oct 16 '22 17:10

John Wu


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

It is created inside the property to limit its scope. If you declared totalCost above the property, it would be accessible throughout the class itself.

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

Usually, just for readability. One liners are great until you have to keep scrolling to see it in its entirety.

like image 3
Inisheer Avatar answered Oct 16 '22 17:10

Inisheer


As mentioned by others, neither of these is really idiomatic C#, however having the backing field for this could lead to errors later on in the code, e.g.:

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 accidentally) accessing the backing variable in the subsequent method, rather than the property you could easily develop some hard to maintain code. In this case, the discounted cost may be right when called, but would depend on the public propery Cost being accessed prior to calling the CalculateDiscountedCost method in order to set the backing variable.

As the backing variable is essentially unnecessary, it would be be better to do without it.

like image 2
Paddy Avatar answered Oct 16 '22 18:10

Paddy


The totalCost variable is not private, it's local variable inside of the getter. The variable does not exist outside of that method so it only takes up memory while the getting is running. Your private cost field will stay in memory as long as the class instance does. The variable is only ever used inside of the getter so it should be a local in the getter as the book shows. There is no reason for it to be a class field.

The point of creating two lines is so that it can fit a single line on the page. The code is exactly the same; it is just formatted differently.

like image 1
shf301 Avatar answered Oct 16 '22 18:10

shf301