6. 文字列指定のAPIを使用しないこと。

なぜなら型の安全性が損なわれるから。そのためにnameofが使えるようになる。

「nameofを使用すると、プロパティの名前を変更した場合、イベントの引数に指定された文字列にも変更が反映される。」これが基本的な用法

Console.WriteLine(nameof(System.Collections.Generic));  // output: Generic
Console.WriteLine(nameof(List<int>));  // output: List
Console.WriteLine(nameof(List<int>.Count));  // output: Count
Console.WriteLine(nameof(List<int>.Add));  // output: Add

var numbers = new List<int> { 1, 2, 3 };
Console.WriteLine(nameof(numbers));  // output: numbers
Console.WriteLine(nameof(numbers.Count));  // output: Count
Console.WriteLine(nameof(numbers.Add));  // output: Add

保守性の高いコードを使うことができる。

    /// <summary>
/// モデル
/// </summary>
public class AmountModel
{
    ///<summary>コード</summary>
    public int Code { get; set; }

    ///<summary>税抜き額</summary>
    public decimal Amount1 { get; set; }

    ///<summary>税額</summary>
    public decimal Amount2 { get; set; }
}


public class Test
{
    public void Main()
    {
        // データ作成
        var amountModel = new AmountModel { Code = 1111, Amount1 = 3000m, Amount2 = 300m };

        // 税込み額計算
        var amount = Calculate(amountModel);

        // 結果
        Console.WriteLine($"税込み額:{amount.ToString()}");

        // 結果出力
        // 税込み額:3300
    }

    /// <summary>
    /// 計算
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    public decimal Calculate<T>(T obj)
    {
        decimal amount = 0m;

        Type type = typeof(T);
        foreach (PropertyInfo property in type.GetProperties())
        {
            switch (property.Name)
            {
                case "Amount1":
                case "Amount2":
                    amount += (decimal)type.GetProperty(property.Name).GetValue(obj, null);
                    break;
                default:
                    break;
            }
        }

        return amount;
    }
}

AmountModelのメンバが変わったとする。

    public class AmountModel
{
    ///<summary>コード</summary>
    public int Code { get; set; }

    ///<summary>税抜き額</summary>
    public decimal TaxExcluded { get; set; }

    ///<summary>税額</summary>
    public decimal TaxAmount { get; set; }
}

この時、次の箇所でエラーは出るので修正可能。

var amountModel = new AmountModel { Code = 1111, TaxExcluded = 3000m, TaxAmount = 300m };

一方で、Testではエラーが出てこないため(switchにひっかからない)、実行すると税込み額:0が表示される。次のように修正すれば正しくコンパイルエラーになるため、修正できる。

    switch (property.Name)
{
    case nameof(AmountModel.Amount1):
    case nameof(AmountModel.Amount2):
        amount += (decimal)type.GetProperty(property.Name).GetValue(obj, null);
        break;
    default:
        break;
}