C#における定数値の扱い方
C#では変わらない値を定義する際に「const」「readonly」を使用すると思います。
何も知らずに使用しているとコードレビューなどで指摘されてしまうこともあるので、整理しておこうと思います。
const
以下、Microsoftのリファレンスを引用してます。
サービスの価格、製品バージョン番号、会社のブランド名などを格納するためには定数フィールドを使用しないでください。
これらの値は時間の経過とともに変更される場合があります。コンパイラは定数を伝達するため、ライブラリでコンパイルされた他のコードを再コンパイルして、変更点を反映することが必要になってしまいます。
つまり、将来変更されることがあるような値には「const」を使用しないということですね。
readonly
以下、Microsoftのリファレンスを引用してます。
readonly キーワードは const キーワードとは異なります。 const フィールドは、フィールドの宣言でしか初期化できません。readonly フィールドは、フィールドの宣言と任意のコンストラクターで複数回割り当てることができます。 このため、readonly フィールドは、使用するコンストラクターに応じて異なる値を持つことができます。 また、次の例のように、const フィールドがコンパイル時定数であるのに対し、readonly フィールドは実行時定数として使用できます。
つまり、言葉の定義としては以下のようになります。
- const フィールド→コンパイル時定数
- readonly フィールド→実行時定数
サンプルコード
商品クラスについて考えてみます。
プロパティとして、以下を用意します。
- ID
- 名前
- 税抜価格
- 税込価格
メソッドとして、以下を用意します。
- 通貨単位をつけて税込価格を返却するメソッド
- 税込価格を計算するメソッド
public sealed class Product
{
/// <summary>消費税 </summary>
private readonly double CONSUMPTION_TAX = 1.1;
/// <summary>通貨単位</summary>
private const string CURRENCY_UNIT = "円";
/// <summary>商品ID</summary>
public string ID { get; }
/// <summary>商品名</summary>
public string Name { get; }
/// <summary>税抜価格</summary>
public string CostPrice { get; }
/// <summary>税込価格</summary>
public string PriceIncludingTax { get; }
public Product(string id, string name, string costPrice)
{
ID = id;
Name = name;
CostPrice = costPrice;
PriceIncludingTax = CulcPriceIncludingTax();
}
/// <summary>単位付きで税込金額を返却する</summary>
public override string ToString()
{
return $"{PriceIncludingTax}{CURRENCY_UNIT}";
}
/// <summary>税込価格を計算する</summary>
private string CulcPriceIncludingTax()
{
double priceIncludingTax = int.Parse(CostPrice) * CONSUMPTION_TAX;
// 四捨五入する
double roundPrice = Math.Ceiling(priceIncludingTax);
return roundPrice.ToString();
}
}
日本では、消費税は変わっていくものですよね。
私が生まれたときは消費税が5%でしたが、今では10%になってしまいました。
つまり、「消費税」はある時点での定数値と言えます。
この場合はreadonlyを使用してあげます。
一方、通貨単位に関してはどうでしょうか?
基本的に「円」という単位は変わらないですよね。
この場合はconstを使用してあげます。
以上、constとreadonlyの使い分けに関してでした。