Выбрать главу

Смешивание закрытых и открытых методов get/set в свойствах

При определении свойств уровень доступа для методов get и set может быть разным. Возвращаясь к номеру карточки социального страхования, если цель заключается в том, чтобы предотвратить модификацию номера извне класса, тогда объявите метод get как открытый, но метод set — как закрытый:

public string SocialSecurityNumber

{

  get => _empSSN;

  private set => _empSSN = value;

}

Обратите внимание, что это превращает свойство, допускающее только чтение, в допускающее чтение и запись. Отличие в том, что запись скрыта от чего-либо за рамками определяющего класса.

Еще раз о ключевом слове static: определение статических свойств

Ранее в главе рассказывалось о роли ключевого слова static. Теперь, когда вы научились использовать синтаксис свойств С#, мы можем формализовать статические свойства. В проекте StaticDataAndMembers класс SavingsAccount имел два открытых статических метода для получения и установки процентной ставки. Однако более стандартный подход предусматривает помещение такого элемента данных в статическое свойство. Ниже приведен пример (обратите внимание на применение ключевого слова static):

// Простой класс депозитного счета.

class SavingsAccount

{

  // Данные уровня экземпляра.

  public double currBalance;

  // Статический элемент данных.

  private static double _currInterestRate = 0.04;

  // Статическое свойство.

  public static double InterestRate

  {

    get { return _currInterestRate; }

    set { _currInterestRate = value; }

  }

  ...

}

Если вы хотите использовать свойство InterestRate вместо предыдущих статических методов, тогда можете модифицировать свой код следующим образом:

// Вывести текущую процентную ставку через свойство.

Console.WriteLine("Interest Rate is: {0}", SavingsAccount.InterestRate);

Сопоставление с образцом и шаблоны свойств (нововведение в версии 8.0)

Шаблон свойств позволяет сопоставлять со свойствами объекта. В качестве примера добавьте к проекту новый файл (EmployeePayTypeEnum.cs) и определите в нем перечисление для типов оплаты сотрудников:

namespace EmployeeApp

{

    public enum EmployeePayTypeEnum

    {

        Hourly,     // почасовая оплата

        Salaried,   // оклад

        Commission  // комиссионное вознаграждение

    }

}

Обновите класс Employee, добавив свойство для типа оплаты и инициализировав его в конструкторе. Ниже показаны изменения, которые понадобится внести в код:

private EmployeePayTypeEnum _payType;

public EmployeePayTypeEnum PayType

{

  get => _payType;

  set => _payType = value;

}

public Employee(string name, int id, float pay, string empSsn)

  : this(name,0,id,pay, empSsn, EmployeePayTypeEnum.Salaried)

{

}

public Employee(string name, int age, int id,

  float pay, string empSsn, EmployeePayTypeEnum payType)

{

  Name = name;

  Id = id;

  Age = age;

  Pay = pay;

  SocialSecurityNumber = empSsn;

  PayType = payType;

}

Теперь, когда все элементы на месте, метод GiveBonus() можно обновить на основе типа оплаты сотрудника. Сотрудники с комиссионным вознаграждением получают премию 10%, с почасовой оплатой — 40-часовой эквивалент соответствующей премии, а с окладом — введенную сумму. Вот модифицированный код метода GiveBonus():

public void GiveBonus(float amount)

{

  Pay = this switch

  {

    {PayType: EmployeePayTypeEnum.Commission }

      => Pay += .10F * amount,

    {PayType: EmployeePayTypeEnum.Hourly }

      => Pay += 40F * amount/2080F,

    {PayType: EmployeePayTypeEnum.Salaried }

      => Pay += amount,

    _ => Pay+=0

  };

}

Как и с другими операторами switch, в которых используется сопоставление с образцом, должен быть предусмотрен общий оператор case или же оператор switch обязан генерировать исключение, если ни один из операторов case не был удовлетворен.