Initializers for auto-implemented properties and getter-only auto properties
The release of C# 6.0 saw two enhancements made to auto-implemented properties. You can now initialize auto-implemented properties inline, and you can also define them without a setter.
Getting ready
To illustrate how to implement these two new enhancements to auto-implemented properties, we will create another class that calculates the sales price after discount for a given barcode and discount type.
How to do it…
- Start off by creating a static class called
Recipe3AutoImplementedProperties
and add theDiscountType
enumerator to the class, along with the auto-implemented properties. You will then initialize those auto-implemented properties with default values:public static class Recipe3AutoImplementedProperties { public enum DiscountType { Sale, Clearout, None } private static int SaleDiscountPercent { get; } = 20; private static int ClearoutDiscountPercent { get; } = 35; public static decimal ShelfPrice { get; set; } = 100; public static decimal SalePrice { get; set; } = 100; }
- The next step is to add the method to calculate the sales price of an item linked to the barcode supplied to the method:
public static void CalculateSalePrice(string barCode, DiscountType discount) { decimal shelfPrice = GetPriceFromBarcode(barCode); if (discount == DiscountType.Sale) SalePrice = (shelfPrice == 0 ? ShelfPrice.CalculateSalePrice(SaleDiscountPercent) : shelfPrice.CalculateSalePrice(SaleDiscountPercent)); if (discount == DiscountType.Clearout) SalePrice = (shelfPrice == 0 ? ShelfPrice.CalculateSalePrice(ClearoutDiscountPercent): shelfPrice.CalculateSalePrice(ClearoutDiscountPercent)); if (discount == DiscountType.None) SalePrice = (shelfPrice == 0 ? ShelfPrice :shelfPrice); }
- In order to simulate a database lookup to find the selling price of a barcode, create another method to return a price for a given barcode:
private static decimal GetPriceFromBarcode(string barCode) { switch (barCode) { case "123450": return 19.95m; case "123451": return 7.55m; case "123452": return 59.99m; case "123453": return 93.99m; default: return 0; } }
- Finally, we will create an extension method class to calculate the sale price after the discount has been applied:
public static class ExtensionMethods { public static decimal CalculateSalePrice(this decimal shelfPrice, int discountPercent) { decimal discountValue = (shelfPrice / 100) * discountPercent; return shelfPrice - discountValue; } }
Note
Extension methods are static methods by default and allow you to extend your code's functionality (extend existing types) without having to modify the original type. You can now have an extension methods class in your solution where you add helpful code. A nice example of using an extension method is to calculate the financial year for a given date. Extension methods are differentiated from other static methods using the
this
keyword in the method signature. In the preceding example, the compiler knows that this is an extension method for the decimal class by looking at the type it extends. - Replace the code of your
Progam.cs
file and run the program:string BarCode = String.Empty; BarCode = "123450"; Chapter1.Recipe3AutoImplementedProperties.CalculateSalePric e(BarCode, Chapter1.Recipe3AutoImplementedProperties.DiscountType.Sale ); Console.WriteLine(Chapter1.Recipe3AutoImplementedProperties .SalePrice);
- The sales price is calculated after applying the sale discount and returned to the console application:
How it works…
If you look at the auto-implemented properties again, you would notice that we have two getter-only auto-implemented properties. All four auto-implemented properties have been initialized with default values. The SaleDiscountPercent
and ClearoutDiscountPercent
properties are read-only. This ensures that the discount values can't be modified in any way.
You will also notice that if the shelf price returned from the GetPriceFromBarcode
method is zero, then the default ShelfPrice
property value is used in determining the discount price. If no discount is applied, the CalculateSalePrice
method simply returns the barcode price. If no price is determined from the barcode, the default ShelfPrice
property value is returned.
Auto-implemented property initializers and getter-only auto-implemented properties are great to cut down on unnecessary if
else
statements. It also makes the code implementing the properties more readable because the intent can be contained in the property itself by initializing it.
Look at what happens if we try to set the SaleDiscountPercent
or ClearoutDiscountPercent
property to a different value:
Visual Studio will emit an error for the getter-only properties because using the get
keyword, we can only read from this property, not assign a value to it.