C#の定数とは?constとreadonlyの違い・使い分けを初心者向けにわかりやすく解説
はじめに
C#でプログラムを書いていると、「定数」という言葉を見かけることがあります。定数とは、簡単にいうと「一度決めたら変更しない値」のことです。
たとえば、消費税率、円周率、最大ログイン試行回数、アプリ名、エラーメッセージなど、プログラムの中で何度も使う値をそのまま直接書くのではなく、名前を付けて管理したい場面があります。
C#では、定数を表すためによく使われるものにconstとreadonlyがあります。どちらも「変更できない値」を扱うための仕組みですが、値が決まるタイミングや使える型、使い方に違いがあります。
この記事では、C#の定数について初心者向けにわかりやすく解説しながら、constとreadonlyの違い、static readonlyの使い方、よくあるエラーや注意点まで順番に紹介します。
1. C#の定数とは?初心者向けに意味をわかりやすく解説
C#の定数を理解するには、まず「変わる値」と「変わらない値」の違いを押さえることが大切です。
プログラムでは、ユーザーの入力内容や計算結果のように、実行中に値が変わるものがあります。一方で、アプリ名や固定の上限値のように、基本的に変えない値もあります。この「変えない値」を安全に扱うために使うのが定数です。
1-1. 定数とは「あとから変更できない値」のこと
定数とは、プログラムの中で一度値を決めたあと、あとから変更できない値のことです。
たとえば、次のように円周率を表す値を定数として定義できます。
C#const double Pi = 3.14;
このように定義したPiには、あとから別の値を代入できません。
C#Pi = 3.14159; // エラー
定数にしておくことで、「この値は途中で変更してはいけない」という意図をコード上で明確にできます。
1-2. 変数と定数の違い
変数は、あとから値を変更できます。
C#int score = 80;
score = 90;
このコードでは、最初にscoreへ80を入れ、そのあと90に変更しています。これは変数なので問題ありません。
一方、定数はあとから値を変更できません。
C#const int MaxScore = 100;
MaxScore = 120; // エラー
つまり、変数は「変わる可能性がある値」、定数は「変えてはいけない値」と考えるとわかりやすいです。
1-3. C#で定数を使うメリット
C#で定数を使うメリットは主に次のとおりです。
まず、コードが読みやすくなります。
C#if (age >= 20)
{
Console.WriteLine("成人です");
}
このコードでも意味はわかりますが、20という数字だけを見ると、何を表しているのか少しわかりにくい場合があります。
定数を使うと、次のように意味が明確になります。
C#const int AdultAge = 20;
if (age >= AdultAge)
{
Console.WriteLine("成人です");
}
AdultAgeという名前が付いているため、「成人年齢を表す値」だとすぐに理解できます。
また、同じ値を複数箇所で使う場合、修正が簡単になります。直接数字や文字列を書いていると、変更時にすべての場所を探して修正しなければなりません。定数にしておけば、定義した場所を見れば値の意味がわかり、管理もしやすくなります。
さらに、誤って値を変更してしまうミスを防げる点も大きなメリットです。
1-4. 定数を使う代表的な場面
C#で定数を使う代表的な場面には、次のようなものがあります。
アプリケーション名のような固定文字列です。
C#const string AppName = "SampleApp";
最大件数や上限値のような固定の数値です。
C#const int MaxRetryCount = 3;
消費税率や手数料率のような固定値です。
C#const decimal TaxRate = 0.1m;
エラーメッセージや表示メッセージのような文字列にも使えます。
C#const string ErrorMessage = "入力内容に誤りがあります。";
このように、プログラム内で意味のある固定値には、定数を使うとコードの可読性と保守性が高まります。
2. C#で定数を定義する方法
C#で定数を定義するときによく使うのがconstです。constを使うと、コンパイル時に値が決まる定数を定義できます。
2-1. constを使った定数の書き方
constを使った定数の基本的な書き方は次のとおりです。
C#const 型名 定数名 = 値;
たとえば、整数の定数を定義する場合は次のように書きます。
C#const int MaxCount = 100;
文字列の定数であれば、次のように書きます。
C#const string SiteName = "My Blog";
constで定義した値は、あとから変更できません。
C#const int MaxCount = 100;
MaxCount = 200; // エラー
2-2. constで定義できる型
constで定義できる型には制限があります。
主に使える型は、数値型、char、bool、string、列挙型などです。
C#const int Count = 10;
const double Rate = 1.5;
const bool IsEnabled = true;
const char Grade = 'A';
const string Message = "Hello";
一方で、DateTimeや配列、クラスのインスタンスなどはconstで定義できません。
C#const DateTime Today = DateTime.Now; // エラー
const int[] Numbers = { 1, 2, 3 }; // エラー
constはコンパイル時に値が確定している必要があるため、実行時に作られる値やオブジェクトには使えないと覚えておきましょう。
2-3. constの基本的なコード例
次のコードは、constを使って最大ログイン試行回数を定義する例です。
C#using System;
class Program
{
const int MaxLoginAttempts = 3;
static void Main()
{
int loginAttempts = 0;
while (loginAttempts < MaxLoginAttempts)
{
Console.WriteLine("ログイン処理を実行します");
loginAttempts++;
}
Console.WriteLine("ログイン試行回数の上限に達しました");
}
}
この例では、MaxLoginAttemptsが定数です。最大ログイン試行回数が3であることが、コード上で明確にわかります。
もしコードの中に直接3と書いていた場合、それが何を意味する数字なのか読み取りにくくなります。定数名を付けることで、数字の意味を説明できるようになります。
2-4. constを使うときの命名規則
C#では、定数名には意味のある名前を付けることが大切です。
たとえば、次のような名前は意味がわかりにくいです。
C#const int N = 10;
const int Value = 100;
一方で、次のように名前を付けると、何を表す値なのかがわかりやすくなります。
C#const int MaxUserNameLength = 20;
const int DefaultPageSize = 50;
C#では、MaxUserNameLengthのように単語の先頭を大文字にするパスカルケースがよく使われます。
なお、他の言語では定数名をMAX_COUNTのようにすべて大文字で書くことがありますが、C#では必ずしもすべて大文字にする必要はありません。C#の一般的な命名規則では、公開する定数やフィールドにはパスカルケースがよく使われます。
3. constとは?C#におけるコンパイル時定数
constは、C#におけるコンパイル時定数です。コンパイル時定数とは、プログラムをコンパイルする時点で値が完全に決まっている定数のことです。
実行してから決まる値ではなく、コードを書いた段階で値が確定している必要があります。
3-1. constは宣言時に値を決める必要がある
constを使う場合、宣言と同時に値を代入しなければなりません。
C#const int MaxCount = 100;
次のように、あとから値を代入することはできません。
C#const int MaxCount;
MaxCount = 100; // エラー
constは「宣言した時点で値が決まっているもの」なので、必ず宣言時に初期化する必要があります。
3-2. constは暗黙的にstaticになる
constで定義したメンバーは、暗黙的にstaticとして扱われます。
たとえば、次のようにクラス内に定数を定義したとします。
C#class AppSettings
{
public const string AppName = "SampleApp";
}
この定数は、インスタンスを作らなくてもクラス名から参照できます。
C#Console.WriteLine(AppSettings.AppName);
つまり、constは特定のインスタンスごとに持つ値ではなく、クラスに属する固定値として扱われます。
そのため、次のようにconstにstaticを付けることはできません。
C#static const int MaxCount = 100; // エラー
constはもともと静的な値として扱われるため、staticを明示的に書く必要はありません。
3-3. constに使える値・使えない値
constに使えるのは、コンパイル時に決まる値です。
C#const int MaxCount = 100;
const string Greeting = "こんにちは";
const double Pi = 3.14;
また、定数同士を使った簡単な計算も可能です。
C#const int BaseValue = 10;
const int DoubleValue = BaseValue * 2;
一方で、実行時に決まる値は使えません。
C#const DateTime Now = DateTime.Now; // エラー
const int RandomValue = new Random().Next(); // エラー
DateTime.Nowはプログラムを実行した時点の日時を返します。つまり、コンパイル時には値が決まっていないため、constには使えません。
3-4. constを使うべきケース
constを使うべきなのは、将来にわたって変わらない値です。
たとえば、数学的な定数や、仕様として絶対に変わらない値にはconstが向いています。
C#public const double Pi = 3.14159;
public const int DaysOfWeek = 7;
また、アプリ内部だけで使う固定値にも利用できます。
C#private const int MaxRetryCount = 3;
ただし、外部のプロジェクトから参照されるpublic constには注意が必要です。constの値は参照側に埋め込まれるため、ライブラリ側で値を変更しても、参照している側を再コンパイルしないと変更が反映されないことがあります。
そのため、外部公開する値や将来変更される可能性がある値には、constではなくstatic readonlyを検討するとよいでしょう。
4. readonlyとは?C#における読み取り専用フィールド
readonlyは、C#で読み取り専用フィールドを定義するためのキーワードです。
constと同じようにあとから自由に変更できない値を扱えますが、readonlyはコンストラクターで値を設定できる点が大きな特徴です。
4-1. readonlyの基本的な書き方
readonlyの基本的な書き方は次のとおりです。
C#readonly 型名 フィールド名;
または、宣言時に値を代入することもできます。
C#readonly int MaxCount = 100;
クラスの中で使う例は次のとおりです。
C#class User
{
private readonly string name;
public User(string userName)
{
name = userName;
}
public void ShowName()
{
Console.WriteLine(name);
}
}
この例では、nameはreadonlyフィールドです。コンストラクターで値を設定したあとは、別の値に変更できません。
4-2. readonlyはコンストラクターで値を設定できる
readonlyの大きな特徴は、コンストラクターの中で値を設定できることです。
C#class Product
{
private readonly int price;
public Product(int productPrice)
{
price = productPrice;
}
}
このように、オブジェクトを作るときに値を決めることができます。
constでは宣言時に値を決める必要がありますが、readonlyであればコンストラクターで値を受け取って設定できます。
C#class Product
{
private const int Price = 1000;
}
上記のようにconstを使うと、すべての商品で同じ価格になってしまいます。商品ごとに価格を変えたい場合は、readonlyの方が適しています。
4-3. readonlyは実行時に値を決められる
readonlyは、実行時に決まる値を扱えます。
たとえば、現在日時を保存したい場合、constではエラーになります。
C#const DateTime CreatedAt = DateTime.Now; // エラー
しかし、readonlyであれば使用できます。
C#class Log
{
private readonly DateTime createdAt;
public Log()
{
createdAt = DateTime.Now;
}
}
このように、readonlyはプログラムの実行中に決まる値を、あとから変更できない形で保持したい場合に便利です。
4-4. readonlyを使うべきケース
readonlyを使うべきなのは、実行時に値を決めたいけれど、その後は変更したくない場合です。
たとえば、次のようなケースです。
C#private readonly DateTime createdAt;
private readonly string userId;
private readonly int timeoutSeconds;
コンストラクターで受け取った値を保存して、その後変更しないようにしたい場合にreadonlyはよく使われます。
また、配列やオブジェクトの参照を変更したくない場合にも使えます。
C#private readonly List<string> names;
ただし、注意点として、readonlyで守られるのは「フィールドに別のオブジェクトを代入できない」ということです。参照先のオブジェクトの中身が変更できるかどうかは、型によって異なります。
C#private readonly List<string> names = new List<string>();
public void AddName(string name)
{
names.Add(name); // これは可能
}
readonlyを付けても、List<T>の中身の追加や削除は可能です。オブジェクト自体を完全に変更不可にしたい場合は、不変な型や読み取り専用コレクションの利用も検討しましょう。
5. constとreadonlyの違いを比較表で解説
constとreadonlyはどちらも「変更しない値」を扱いますが、仕組みは大きく異なります。
初心者のうちは混同しやすいため、まずは比較表で全体像を確認しましょう。
| 比較項目 | const | readonly |
|---|---|---|
| 値が決まるタイミング | コンパイル時 | 実行時 |
| 初期化できる場所 | 宣言時のみ | 宣言時またはコンストラクター |
| staticの扱い | 暗黙的にstatic | 通常はインスタンスごと。staticも指定可能 |
| 使える型 | 数値、bool、char、string、enumなど | 多くの型で使用可能 |
| DateTime | 使えない | 使える |
| 配列・オブジェクト | 基本的に使えない | 使える |
| 値の変更 | 不可 | 初期化後は不可 |
| 主な用途 | 絶対に変わらない固定値 | 実行時に決まる読み取り専用値 |
5-1. 値が決まるタイミングの違い
constはコンパイル時に値が決まります。
C#const int MaxCount = 100;
この100という値は、プログラムをコンパイルする時点で確定しています。
一方、readonlyは実行時に値を決められます。
C#readonly DateTime createdAt;
public Sample()
{
createdAt = DateTime.Now;
}
DateTime.Nowはプログラムを実行したときに決まる値なので、constでは使えません。しかし、readonlyならコンストラクターで設定できます。
5-2. 初期化できる場所の違い
constは宣言時にしか初期化できません。
C#const int MaxCount = 100;
次のようにコンストラクターで設定することはできません。
C#class Sample
{
const int MaxCount;
public Sample()
{
MaxCount = 100; // エラー
}
}
一方、readonlyは宣言時またはコンストラクターで初期化できます。
C#class Sample
{
readonly int maxCount;
public Sample()
{
maxCount = 100;
}
}
この違いは、constとreadonlyを使い分けるうえで非常に重要です。
5-3. staticの扱いの違い
constは暗黙的にstaticです。
C#class Constants
{
public const int MaxCount = 100;
}
この定数は、クラス名から直接参照できます。
C#Console.WriteLine(Constants.MaxCount);
一方、readonlyは通常、インスタンスごとのフィールドです。
C#class User
{
public readonly string Name;
public User(string name)
{
Name = name;
}
}
この場合、Nameは作成したインスタンスごとに異なる値を持てます。
C#User user1 = new User("田中");
User user2 = new User("佐藤");
クラス全体で共通の読み取り専用値にしたい場合は、static readonlyを使います。
C#class Settings
{
public static readonly DateTime StartedAt = DateTime.Now;
}
5-4. 使える型の違い
constで使える型は限られています。
C#const int Count = 10;
const string Name = "CSharp";
const bool IsActive = true;
DateTimeや配列、List<T>などはconstにできません。
C#const DateTime Now = DateTime.Now; // エラー
一方、readonlyはさまざまな型に使えます。
C#readonly DateTime createdAt;
readonly int[] numbers;
readonly List<string> names;
そのため、オブジェクトや日付、設定クラスなどを扱う場合はreadonlyが適しています。
5-5. パフォーマンスや保守性の違い
constはコンパイル時に値が埋め込まれるため、単純な固定値では効率的です。
ただし、保守性の面では注意が必要です。特に、ライブラリでpublic constとして公開している値を変更した場合、参照している側のアプリケーションを再コンパイルしないと、古い値が使われ続ける可能性があります。
一方、readonlyやstatic readonlyは実行時にフィールドを参照します。そのため、外部公開する値や将来変更される可能性がある値では、constよりもstatic readonlyの方が安全な場合があります。
パフォーマンスだけで考えるとconstは軽量ですが、実務では保守性も重要です。単に速さだけでなく、「その値が将来変わる可能性があるか」「外部から参照されるか」を考えて選ぶことが大切です。
6. constとreadonlyの使い分け方
constとreadonlyの使い分けで迷ったときは、「その値は本当に永遠に変わらないか」を考えると判断しやすくなります。
6-1. 絶対に変わらない値はconstを使う
数学的な値や仕様上絶対に変わらない値には、constが向いています。
C#public const double Pi = 3.14159;
public const int MonthsInYear = 12;
このような値は、将来変更される可能性がほとんどありません。
また、クラス内部だけで使う固定値にもconstは便利です。
C#private const int MaxRetryCount = 3;
private constであれば、そのクラスの中だけで使われるため、外部プロジェクトへの影響も少なくなります。
6-2. 将来変更される可能性がある値はreadonlyを使う
将来変更される可能性がある値には、readonlyまたはstatic readonlyを使う方が安全です。
たとえば、次のような値は一見固定に見えても、仕様変更で変わる可能性があります。
C#public static readonly int DefaultPageSize = 50;
public static readonly decimal TaxRate = 0.1m;
消費税率やページサイズ、制限値などは、将来的に変更されることがあります。そのため、外部に公開する場合はconstよりもstatic readonlyを検討するとよいでしょう。
6-3. 外部公開する値はstatic readonlyを検討する
ライブラリや共通プロジェクトで外部に公開する値には、public constを使うと注意が必要です。
C#public const int MaxCount = 100;
この値を別プロジェクトが参照している場合、MaxCountの値を200に変更してライブラリを更新しても、参照側が再コンパイルされないと古い値が使われることがあります。
そのため、外部公開する値には次のようにstatic readonlyを使う選択肢があります。
C#public static readonly int MaxCount = 100;
static readonlyであれば、実行時にフィールドとして参照されるため、constより変更に強い設計にしやすくなります。
6-4. 設定値・日付・オブジェクトにはreadonlyを使う
設定値、日時、オブジェクトなど、実行時に決まる値にはreadonlyを使います。
C#private readonly DateTime createdAt;
private readonly string connectionString;
private readonly HttpClient httpClient;
たとえば、コンストラクターで設定値を受け取る場合は、readonlyが適しています。
C#class ApiClient
{
private readonly string baseUrl;
public ApiClient(string baseUrl)
{
this.baseUrl = baseUrl;
}
}
このようにすることで、baseUrlはオブジェクト作成時に決まり、その後は変更されません。
6-5. 迷ったときの判断基準
constとreadonlyで迷ったときは、次のように考えると判断しやすいです。
値がコンパイル時に決まっていて、将来ほぼ変わらない場合はconstを使います。
C#private const int DaysInWeek = 7;
値が実行時に決まる場合や、将来変更される可能性がある場合はreadonlyを使います。
C#private readonly DateTime createdAt;
クラス全体で共通の読み取り専用値にしたい場合はstatic readonlyを使います。
C#public static readonly string AppName = "SampleApp";
特に初心者のうちは、「本当にconstでなければならないか」と考えるのがおすすめです。少しでも変更の可能性がある値や、外部公開する値にはstatic readonlyを選ぶと安全なケースが多いです。
7. static readonlyとは?constとの違いも解説
static readonlyは、クラス全体で共有される読み取り専用フィールドです。
readonlyは通常インスタンスごとの値ですが、staticを付けることで、クラスに属する共通の値として扱えます。
7-1. static readonlyの基本的な書き方
static readonlyの基本的な書き方は次のとおりです。
C#static readonly 型名 フィールド名 = 値;
たとえば、アプリケーションの開始時刻を保持する場合は次のように書けます。
C#class AppInfo
{
public static readonly DateTime StartedAt = DateTime.Now;
}
この値はクラス全体で共有され、あとから変更できません。
C#Console.WriteLine(AppInfo.StartedAt);
DateTime.Nowは実行時に決まる値なので、constにはできません。しかし、static readonlyなら定義できます。
7-2. static readonlyがよく使われる理由
static readonlyがよく使われる理由は、実行時に値を決められ、かつクラス全体で共有できるからです。
たとえば、次のようなケースで便利です。
C#public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);
TimeSpan.FromSeconds(30)はメソッド呼び出しなので、constには使えません。しかし、static readonlyなら使用できます。
また、オブジェクトを共通の読み取り専用値として持ちたい場合にも使えます。
C#public static readonly string[] SupportedExtensions = { ".jpg", ".png", ".gif" };
ただし、配列は中身を変更できる点に注意が必要です。
C#SupportedExtensions[0] = ".bmp"; // 配列の中身は変更できてしまう
完全に変更されないコレクションにしたい場合は、読み取り専用コレクションなどを利用するとよいでしょう。
7-3. constではなくstatic readonlyを選ぶべき場面
constではなくstatic readonlyを選ぶべき場面は、実行時に値を決める必要がある場合です。
C#public static readonly DateTime ReleaseDate = new DateTime(2026, 1, 1);
new DateTime(...)はconstにはできません。そのため、日付を固定値として扱いたい場合でもstatic readonlyを使います。
また、外部公開する値にもstatic readonlyが向いています。
C#public static readonly int DefaultPageSize = 50;
将来変更される可能性がある値をpublic constにすると、参照側に古い値が残る可能性があります。そのため、ライブラリや共通部品ではstatic readonlyを選ぶ方が保守しやすい場合があります。
7-4. const・readonly・static readonlyの違い
const、readonly、static readonlyの違いをまとめると次のようになります。
| 種類 | 特徴 | 主な用途 |
|---|---|---|
| const | コンパイル時に値が決まる定数 | 絶対に変わらない固定値 |
| readonly | インスタンスごとに設定できる読み取り専用フィールド | コンストラクターで決める値 |
| static readonly | クラス全体で共有する読み取り専用フィールド | 実行時に決まる共通値、外部公開する固定値 |
たとえば、次のように使い分けます。
C#class Sample
{
private const int MaxRetryCount = 3;
private readonly string userName;
public static readonly DateTime AppStartedAt = DateTime.Now;
public Sample(string userName)
{
this.userName = userName;
}
}
MaxRetryCountはコンパイル時に決まる固定値です。userNameはインスタンスごとに異なる値です。AppStartedAtはアプリ全体で共有される実行時の値です。
8. C#の定数でよくあるエラーと注意点
C#の定数を使うときには、いくつか初心者がつまずきやすいポイントがあります。
特に、constとreadonlyの違いを理解していないと、コンパイルエラーになったり、思ったように値が反映されなかったりすることがあります。
8-1. constに変数や計算結果を代入できない
constには、実行時に決まる変数や計算結果を代入できません。
C#int baseValue = 10;
const int result = baseValue * 2; // エラー
baseValueは変数なので、コンパイル時定数ではありません。そのため、constには使えません。
ただし、const同士の計算であれば使用できます。
C#const int BaseValue = 10;
const int Result = BaseValue * 2;
この場合、BaseValueもコンパイル時定数なので、Resultもコンパイル時に値を決められます。
8-2. constにDateTimeや配列を指定できない
DateTimeや配列はconstにできません。
C#const DateTime CreatedAt = DateTime.Now; // エラー
const int[] Numbers = { 1, 2, 3 }; // エラー
日付を固定値として扱いたい場合は、static readonlyを使います。
C#public static readonly DateTime CreatedAt = new DateTime(2026, 1, 1);
配列を共有したい場合も、static readonlyを使うことがあります。
C#public static readonly int[] Numbers = { 1, 2, 3 };
ただし、配列の中身は変更できるため、完全な意味での定数ではありません。
C#Numbers[0] = 99; // 可能
配列の中身も変更されたくない場合は、設計を工夫する必要があります。
8-3. readonlyはローカル変数には使えない
readonlyはフィールドに使うキーワードです。メソッドの中のローカル変数には使えません。
次のコードはエラーになります。
C#void Sample()
{
readonly int count = 10; // エラー
}
メソッド内で再代入したくないローカル変数を表したい場合、C#では通常のローカル変数として扱い、再代入しないように書きます。
C#void Sample()
{
int count = 10;
Console.WriteLine(count);
}
readonlyは、クラスや構造体のフィールドに対して使うものだと覚えておきましょう。
8-4. constの値変更が反映されないケース
constの注意点として、値が参照側に埋め込まれることがあります。
たとえば、ライブラリ側で次のような定数を公開していたとします。
C#public const int MaxCount = 100;
別のプロジェクトがこの定数を参照している場合、コンパイル時に100という値が参照側に埋め込まれることがあります。
その後、ライブラリ側で値を変更します。
C#public const int MaxCount = 200;
しかし、参照側のプロジェクトを再コンパイルしないと、古い100が使われ続ける可能性があります。
この問題を避けたい場合は、外部公開する値にstatic readonlyを使うことを検討します。
C#public static readonly int MaxCount = 200;
public constは便利ですが、ライブラリや共通部品では慎重に使いましょう。
8-5. マジックナンバーを定数化するときの注意点
マジックナンバーとは、コードの中に直接書かれた意味のわかりにくい数値のことです。
C#if (score >= 80)
{
Console.WriteLine("合格です");
}
この80が何を意味するのか、コードだけでは少しわかりにくい場合があります。
定数化すると、意味がわかりやすくなります。
C#const int PassingScore = 80;
if (score >= PassingScore)
{
Console.WriteLine("合格です");
}
ただし、何でも定数化すればよいわけではありません。
たとえば、ループで使う一時的な0や1まで無理に定数化すると、逆にコードが読みにくくなることがあります。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
このような一般的な使い方では、0をわざわざStartIndexのような定数にする必要がない場合もあります。
定数化すべきなのは、ビジネスルールや仕様上の意味を持つ値です。数字や文字列に名前を付けることで意味が明確になる場合に、定数を使うと効果的です。
9. C#の定数に関するよくある質問
ここでは、C#の定数について初心者が疑問に感じやすいポイントをQ&A形式で解説します。
9-1. C#で定数はconstだけですか?
C#で「定数」と聞くとconstを思い浮かべることが多いですが、変更できない値を扱う方法はconstだけではありません。
代表的なものに、const、readonly、static readonlyがあります。
constはコンパイル時に値が決まる定数です。
C#const int MaxCount = 100;
readonlyは、コンストラクターで値を設定できる読み取り専用フィールドです。
C#readonly string name;
static readonlyは、クラス全体で共有される読み取り専用フィールドです。
C#public static readonly DateTime StartedAt = DateTime.Now;
厳密にはconstとreadonlyは仕組みが異なりますが、実務ではどちらも「変更しない値」を扱うために使われます。
9-2. constとreadonlyはどちらを使えばいいですか?
絶対に変わらない値で、コンパイル時に値が決まる場合はconstを使います。
C#private const int DaysInWeek = 7;
一方、実行時に値が決まる場合や、コンストラクターで値を設定したい場合はreadonlyを使います。
C#private readonly DateTime createdAt;
public Sample()
{
createdAt = DateTime.Now;
}
また、外部公開する値や将来変更される可能性がある値は、static readonlyを検討するとよいでしょう。
C#public static readonly int DefaultPageSize = 50;
初心者のうちは、「コンパイル時に決まる完全固定値ならconst」「実行時に決まるならreadonly」「共通で使う読み取り専用値ならstatic readonly」と覚えると理解しやすいです。
9-3. constとstatic readonlyはどちらが速いですか?
単純な値の参照だけで見れば、constはコンパイル時に値が埋め込まれるため、非常に軽量です。
C#const int MaxCount = 100;
一方、static readonlyは実行時にフィールドを参照します。
C#static readonly int MaxCount = 100;
ただし、通常のアプリケーション開発では、この差が問題になることはほとんどありません。パフォーマンスだけで選ぶよりも、保守性や値の変更可能性を考えて選ぶことが大切です。
将来変わらない値ならconst、変更の可能性がある値や外部公開する値ならstatic readonlyを選ぶとよいでしょう。
9-4. 定数名は大文字にするべきですか?
C#では、定数名を必ずすべて大文字にする必要はありません。
他の言語では、次のような書き方がよく使われます。
C#const int MAX_COUNT = 100;
しかし、C#では一般的にパスカルケースが使われることが多いです。
C#const int MaxCount = 100;
特に、公開メンバーや定数にはMaxCount、DefaultPageSize、ConnectionTimeoutのような名前がよく使われます。
大切なのは、プロジェクト内で命名規則を統一することです。チーム開発では、既存のコードやコーディング規約に合わせるようにしましょう。
9-5. enumと定数はどう使い分けますか?
enumは、関連する複数の固定値をまとめて扱いたい場合に使います。
たとえば、ユーザーの状態を表す場合です。
C#enum UserStatus
{
Active,
Inactive,
Suspended
}
このように、選択肢が決まっている値にはenumが向いています。
一方、単独の固定値には定数を使います。
C#const int MaxLoginAttempts = 3;
const string DefaultUserName = "Guest";
つまり、複数の関連する選択肢を表したい場合はenum、単独の固定値に名前を付けたい場合はconstやreadonlyを使うと考えるとわかりやすいです。
まとめ
C#の定数とは、あとから変更できない値のことです。プログラム内で意味のある固定値に名前を付けることで、コードが読みやすくなり、修正もしやすくなります。
C#で定数を扱う代表的な方法には、const、readonly、static readonlyがあります。
constはコンパイル時に値が決まる定数です。宣言時に値を設定する必要があり、数値、文字列、bool、char、enumなどに使えます。絶対に変わらない固定値に向いています。
readonlyは読み取り専用フィールドです。宣言時だけでなく、コンストラクターで値を設定できます。実行時に値を決めたい場合や、インスタンスごとに異なる値を持たせたい場合に便利です。
static readonlyは、クラス全体で共有される読み取り専用フィールドです。DateTimeやオブジェクト、外部公開する値、将来変更される可能性がある値に使われることがよくあります。
使い分けの目安は、絶対に変わらない値ならconst、実行時に決まる値ならreadonly、クラス全体で共有したい読み取り専用値ならstatic readonlyです。
C#の定数を正しく使うと、マジックナンバーを減らし、コードの意味を明確にできます。初心者のうちは、まずconstとreadonlyの違いを理解し、値が決まるタイミングに注目して使い分けることから始めましょう。

