Read/Write-Only Properties

Introduction

One of the goals of a property is to serve as a gateway between an object and its clients. One of the ways this gateway works is through the exchange of values between two objects. To keep this exchange in check, a property can be used to validate, then accept or reject the values that an object receives. A property can also be used to perform calculations on values received from client objects. To take of these and other situation, you can create one or more conditional statements in the body of a property.

Practical LearningPractical Learning: Introducing Properties

  1. Start Microsoft Visual Studio and, on the Visual Studio 2019 dialog box, click Create a New Project (if Microsoft Visual Studio was already running, on the main menu, click File -> New -> Project...)
  2. In the list of projects templates, click Windows Forms App (.NET Framework)
  3. Click Next
  4. Change the project Name to ESCAPE3
  5. Click Create
  6. Design the form as follows:

    Introduction to Logical Operations

    Control (Name) Text Other Properties
    Label   Eastern Shore Company Associates for Production Entertainment  
    GroupBox   Customer Account  
    Label   Account Number:  
    TextBox txtAccountNumber    
    Label   The customer wants:  
    Label   Account Type:  
    ComboBox cbxAccountsTypes   Items:
    Hospital
    Commercial
    Government
    Residential
    Senior Living
    CheckBox chkDVRService DVR Service CheckAlign: MiddleRight
    Label   Number of Units:  
    TextBox txtNumberOfUnits 1 TextAlign: Right
    CheckBox chkSportsPackage Sports Package CheckAlign: MiddleRight
    Label   State:  
    ComboBox cbxStates   Items:
    Kansas
    Missouri
    Label   Locality:  
    TextBox txtLocality TextAlign: Right
    Button btnEvaluate Evaluate Bill  
    GroupBox   Bill Evaluation  
    Label   Bill Number:  
    TextBox txtBillNumber
    Label   Package Fee:
    TextBox txtPackageFee   TextAlign: Right
    Label   Additional Units:
    TextBox txtAdditionalUnits   TextAlign: Right
    Label   Additional Units Fee:
    TextBox txtAdditionalUnitsFee   TextAlign: Right
    Label   DVR Service:  
    TextBox txtDVRService TextAlign: Right
    Label   Sports Package:  
    TextBox txtSportsPackage TextAlign: Right
    Label   __________________  
    Label   Sub-Total:  
    TextBox txtSubTotal   TextAlign: Right
    Label   Local Taxes:  
    TextBox txtLocalTaxes   TextAlign: Right
    Label   FCC Fee:  
    TextBox txtFCCFee   TextAlign: Right
    Label   State Taxes:  
    TextBox txtStateTaxes   TextAlign: Right
    Label   Amount Due:  
    TextBox txtAmountDue   TextAlign: Right
  7. Double-click the Calculate button
  8. Right-click inside the Code Editor and click Remove and Sort Usings
  9. In the Solution Explorer, right-click ESCAPE3 -> Add -> Class..
  10. Change the name to Customer
  11. Press Enter
  12. Change the code as follows:
    namespace ESCAPE3
    {
        public class Customer
        {
            public string AccountNumber { get; set; }
            public string AccountType { set; get; }
            public int NumberOfUnits { get; set; }
            public bool DVRServiced { set; get; }
            public bool RequestsSportsPackage { get; set; }
            public string State { set; get; }
            public string Locality { get; set; }
        }
    }
  13. On the main menu, click Project -> Add Class...
  14. Type CableBill
  15. Press Enter

A Conditional Statement in a Property Reader

A read-only property allows an object to provide values to other objects. Instead of just giving simple values, you can use such a property to perform meaning calculations that are based on some conditions. Any of the conditional statement we have studied so far can be used.

Besides simple conditional statements, we saw that you can create a local function in the body of a clause of a property.

Practical LearningPractical Learning: Introducing Condition Statements in Properties

  1. Change the CableBill class as follows:
    namespace ESCAPE3
    {
        public class CableBill
        {
            public CableBill()
            {
                Client = new Customer();
            }
    
            public int BillNumber { get; set; }
            public Customer Client { get; set; }
            public double PrimaryPackageFee
            {
                get
                {
                    double pay = 0.00;
    
                    switch (Client.AccountType)
                    {
                        case "Senior Living":
                            pay = 9.65;
                            break;
                        case "Hospital":
                            pay = 12.55;
                            break;
                        case "Commercial":
                            pay = 24.35;
                            break;
                        case "Government":
                            pay = 21.25;
                            break;
                        case null:
                            pay = 16.95;
                            break;
                    }
    
                    return pay;
                }
            }
    
            public int AdditionalUnits
            {
                get
                {
                    int units = 0;
    
                    if (Client.NumberOfUnits > 1)
                        units = Client.NumberOfUnits - 1;
    
                    return units;
                }
            }
            public double AdditionalUnitsFee
            {
                get
                {
                    double additional = 0.00;
    
                    if (Client.NumberOfUnits > 1)
                        additional = 9.95 * Client.NumberOfUnits;
    
                    return PrimaryPackageFee + additional;
                }
            }
            public double DVRFee
            {
                get
                {
                    double fee = 0.00;
    
                    if (Client.DVRServiced == true)
                        fee = 6.65;
    
                    return fee;
                }
            }
            public double SportsPackageFee
            {
                get
                {
                    double fee = 0.00;
    
                    if (Client.RequestsSportsPackage == true)
                        fee = 8.85;
    
                    return fee;
                }
            }
            public double SubTotal
            {
                get
                {
                    return PrimaryPackageFee + AdditionalUnitsFee + DVRFee + SportsPackageFee;
                }
            }
            public double FCCFee
            {
                get
                {
                    return SubTotal * 0.00250881;
                }
            }
            public double LocalTaxes
            {
                get
                {
                    return (SubTotal + FCCFee) * 0.0372668;
                }
            }
            public double StateTaxes
            {
                get
                {
                    return (SubTotal + FCCFee) * 0.0082493;
                }
            }
    
            public double AmountDue
            {
                get
                {
                    return SubTotal + FCCFee + LocalTaxes + StateTaxes;
                }
            }
        }
    }
  2. On the main menu, click Window -> Form1.cs
  3. Change the document as follows:
    using System;
    using System.Windows.Forms;
    
    namespace ESCAPE3
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            Customer Identify()
            {
                return new Customer()
                {
                    AccountNumber = txtAccountNumber.Text,
                    AccountType = cbxAccountsTypes.Text,
                    NumberOfUnits = int.Parse(txtNumberOfUnits.Text),
                    DVRServiced = chkDVRService.Checked,
                    RequestsSportsPackage = chkSportsPackage.Checked,
                    State = cbxStates.Text,
                    Locality = txtLocality.Text
                };
            }
    
            private void btnEvaluate_Click(object sender, EventArgs e)
            {
                CableBill cb = new CableBill();
                Random rndNumber = new Random();
    
                cb.Client = Identify();
    
                txtBillNumber.Text = rndNumber.Next(1, 1000000).ToString();
                txtPackageFee.Text = cb.PrimaryPackageFee.ToString("F");
                txtAdditionalUnits.Text = cb.AdditionalUnits.ToString("F");
                txtAdditionalUnitsFee.Text = cb.AdditionalUnitsFee.ToString("F");
                txtDVRService.Text = cb.DVRFee.ToString("F");
                txtSportsPackage.Text = cb.SportsPackageFee.ToString("F");
                txtSubTotal.Text = cb.SubTotal.ToString("F");
                txtFCCFee.Text = cb.FCCFee.ToString("F");
                txtLocalTaxes.Text = cb.LocalTaxes.ToString("F");
                txtStateTaxes.Text = cb.StateTaxes.ToString("F");
                txtAmountDue.Text = cb.AmountDue.ToString("F");
            }
        }
    }
  4. To execute the project, on the main menu, click Debug -> Start Without Debugging:

    Finding Out Whether a Value is Greater Than Another Value

  5. In the Customer Account section, set the following values:
    Account Number:  861402
    Account Type:    Commercial
    Number of Units: 6
    State:           Kansas
    Locality:        Neighborhood

    Finding Out Whether a Value is Greater Than Another Value

  6. Click the Evaluate Bill button:

    Finding Out Whether a Value is Greater Than Another Value

  7. Close the form and return to your programming environment

A Property with a Simple Return Statement

Most read-only properties contain a single line of code that returns their values. Such properties don't need a body delimited by curly brackets. For such a property, replace the opening curly bracket with the => operator, replace the get { return } expression with the statement to return, and omit the closing curly bracket.

Practical LearningPractical Learning: Creating and Using Read-Only Properties

  1. Click the CableBill.cs tab
  2. Change some of the properties in the class as follows:
    namespace ESCAPE3
    {
        public class CableBill
        {
            public CableBill() => Client = new Customer();
    
            public int BillNumber { get; set; }
            public Customer Client { get; set; }
            public double PrimaryPackageFee
            {
                get
                {
                    double pay = 0.00;
    
                    switch (Client.AccountType)
                    {
                        case string _ when Client.AccountType == "Senior Living":
                            pay = 9.65;
                            break;
                        case string _ when Client.AccountType == "Hospital":
                            pay = 14.25;
                            break;
                        case string _ when Client.AccountType == "Commercial":
                            pay = 24.35;
                            break;
                        case string _ when Client.AccountType == "Government":
                            pay = 21.25;
                            break;
                        case null:
                            pay = 18.95;
                            break;
                    }
    
                    return pay;
                }
            }
    
            public int AdditionalUnits
            {
                get
                {
                    if (Client.NumberOfUnits > 1)
                        return Client.NumberOfUnits - 1;
                    else
                        return 0;
                }
            }
            public double AdditionalUnitsFee
            {
                get
                {
                    if (Client.NumberOfUnits > 1)
                        return 12.95 * Client.NumberOfUnits;
                    else
                        return PrimaryPackageFee;
                }
            }
            public double DVRFee
            {
                get
                {
                    if (Client.DVRServiced == true)
                        return 6.85;
                    else
                        return 0.00;
                }
            }
            public double SportsPackageFee
            {
                get
                {
                    if (Client.RequestsSportsPackage == true)
                        return 8.95;
                    else
                        return 0.00;
                }
            }
    
            public double SubTotal   =>  PrimaryPackageFee + AdditionalUnitsFee + DVRFee + SportsPackageFee;
            public double FCCFee     =>  SubTotal * 0.00250881;
            public double LocalTaxes => (SubTotal + FCCFee) * 0.0372668;
            public double StateTaxes => (SubTotal + FCCFee) * 0.0082493;
            public double AmountDue  =>  SubTotal + FCCFee + LocalTaxes + StateTaxes;
        }
    }
  3. To execute the project, press Ctrl + F5
  4. In the Customer Account section, set the following values:
    Account Number:  247947
    Account Type:    Residential
    Number of Units: 3
    State:           Missouri
    Sports Package:  Checked
    Locality:        Odessa

    Finding Out Whether a Value is Greater Than Another Value

  5. Click the Evaluate Bill button:

    Finding Out Whether a Value is Greater Than Another Value

  6. Close the form and return to your programming environment

The Ternary Operator (?:)

As you may remember, the ternary operator is used to simplify the code of an if...else conditional statement. You can use the ternary operator to create such a statement in property.

Practical LearningPractical Learning: Using the Ternary Operator

  1. Change the code as follows:
    namespace ESCAPE3
    {
        public class CableBill
        {
            public CableBill() => Client = new Customer();
    
            public int BillNumber { get; set; }
            public Customer Client { get; set; }
            public double PrimaryPackageFee
            {
                get
                {
                    double pay = 0.00;
    
                    switch (Client.AccountType)
                    {
                        case string _ when Client.AccountType == "Senior Living":
                            pay = 10.55;
                            break;
                        case string _ when Client.AccountType == "Hospital":
                            pay = 16.55;
                            break;
                        case string _ when Client.AccountType == "Commercial":
                            pay = 24.35;
                            break;
                        case string _ when Client.AccountType == "Government":
                            pay = 22.35;
                            break;
                        case null:
                            pay = 19.75;
                            break;
                    }
    
                    return pay;
                }
            }
    
            public int AdditionalUnits
            {
                get
                {
                    return (Client.NumberOfUnits > 1) ? Client.NumberOfUnits - 1 : 0;
                }
            }
            public double AdditionalUnitsFee
            {
                get
                {
                    return (Client.NumberOfUnits > 1) ? 
                           12.95 * Client.NumberOfUnits : 
                           PrimaryPackageFee;
                }
            }
            public double DVRFee
            {
                get
                {
                    return (Client.DVRServiced == true) ? 6.85 : 0.00;
                }
            }
            public double SportsPackageFee
            {
                get
                {
                    return (Client.RequestsSportsPackage == true) ? 8.95 : 0.00;
                }
            }
            public double SubTotal   => PrimaryPackageFee + AdditionalUnitsFee + DVRFee + SportsPackageFee;
            public double FCCFee     => SubTotal * 0.00250881;
            public double LocalTaxes => (SubTotal + FCCFee) * 0.0372668;
            public double StateTaxes => (SubTotal + FCCFee) * 0.0082493;
            public double AmountDue  => SubTotal + FCCFee + LocalTaxes + StateTaxes;
        }
    }
  2. To execute, on the main menu, click Debug -> Start Without Debugging
  3. In the Customer Account section, set the following values:
    Account Number:  537508
    Account Type:    Senior Living
    Number of Units: 58
    State:           Kansas
    DVR Service:     Checked
    Locality:        Holden

    Finding Out Whether a Value is Greater Than Another Value

  4. Click the Evaluate Bill button:

    Finding Out Whether a Value is Greater Than Another Value

  5. Close the form and return to Microsoft Visual Studio

An Expession-Bodied Property

Another way to reduce the amount of code involved with a property os to create it as an expression-bodied member. In this case, replace the return keyword with the => operator.

Practical LearningPractical Learning: Creating Expession-Bodied Properties

  1. Change the code as follows:
    namespace ESCAPE3
    {
        public class CableBill
        {
            public CableBill()    => Client = new Customer();
    
            public int BillNumber  { get; set; }
            public Customer Client { get; set; }
            public double PrimaryPackageFee
            {
                get
                {
                    double pay = 0.00;
    
                    switch (Client.AccountType)
                    {
                        case string _ when Client.AccountType == "Senior Living":
                            pay = 10.55;
                            break;
                        case string _ when Client.AccountType == "Hospital":
                            pay = 16.55;
                            break;
                        case string _ when Client.AccountType == "Commercial":
                            pay = 24.35;
                            break;
                        case string _ when Client.AccountType == "Government":
                            pay = 22.35;
                            break;
                        case null:
                            pay = 19.75;
                            break;
                    }
    
                    return pay;
                }
            }
    
            public int AdditionalUnits
            {
                get => (Client.NumberOfUnits > 1) ? Client.NumberOfUnits - 1 : 0;
            }
            public double AdditionalUnitsFee
            {
                get => (Client.NumberOfUnits > 1) ? 
                        12.95 * Client.NumberOfUnits : 
                        PrimaryPackageFee;
            }
            public double DVRFee
            {
                get => (Client.DVRServiced == true) ? 6.85 : 0.00;
            }
            public double SportsPackageFee
            {
                get => (Client.RequestsSportsPackage == true) ? 8.95 : 0.00;
            }
            public double SubTotal   => PrimaryPackageFee + AdditionalUnitsFee + DVRFee + SportsPackageFee;
            public double FCCFee     => SubTotal * 0.00250881;
            public double LocalTaxes => (SubTotal + FCCFee) * 0.0372668;
            public double StateTaxes => (SubTotal + FCCFee) * 0.0082493;
            public double AmountDue  => SubTotal + FCCFee + LocalTaxes + StateTaxes;
        }
    }
  2. To execute, press Ctrl + F5
  3. Close the form and return to Microsoft Visual Studio

A Conditional Statement in a Property Writer

A property writer allows external objects to provide a value to its corresponding fields in the class. Because of this, and since it is through the writer that the external objects may change the value of the field, you can use the property writer to validate or reject a new value assigned to the field. Remember that the client objects of the class can only read the value of the field through the property reader. Therefore, there may be only little concern on that side. Here is an example:

public class TimeSheet
{
    private double day;

    public double Overtime
    {
	    set
 	    {
	        // A day contains only 24 hours. There is no way somebody can work over 24 hours.
    	    if( day > 24 )
		        day = 0.00;
    	    else
    	       	day = value;
	    }
    }
}

Read/Write Properties

Introduction

Although most of your applications will use automatic properties, in many other applications, you will want to deciunder what circumtances and what values are allow to the objects of the class and what values should be refected. To take care of this, you can use either or both clauses of a property. Here is an example:

public class TimeSheet
{
    private double day;

    public double Overtime
    {
        get
        {
            if (day <= 8.00)
                return 0.00;
            else
                return day - 8.00;
        }
    	set
    	{
	        if( day > 24 )
	            day = 0.00;
            else
        	    day = value;
	    }
    }
}

Simplifying the Code on Properties

To simplify the coe of a property, you can use the => operator on a simple clause. If your code is using a simple if...else conditional statement, you can simplify that code with a ternary operator.

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2021, FunctionX Next