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;
}