C# constantsとは?constの使い方・readonlyとの違い・命名規則まで初心者向けに解説

はじめに

C#でプログラムを書いていると、数値や文字列など「一度決めたら変えたくない値」を扱う場面がよくあります。

たとえば、消費税率、最大文字数、エラーメッセージ、設定値、固定のコード値などです。

C#
const int MaxUserNameLength = 20;
const string ErrorMessage = "入力内容に誤りがあります。";

このような値は、毎回コードの中に直接書くのではなく、定数として名前を付けて管理すると、コードが読みやすくなり、修正もしやすくなります。

英語では定数のことを「constant」と呼びます。そのため、C#の定数について調べるときに「csharp constants」や「C# constants」と検索する人も多いでしょう。

C#には、定数や変更不可の値を扱うために、主に次のような仕組みがあります。

C#
const
readonly
static readonly

この記事では、C# constantsの基本から、constの使い方、readonlystatic readonlyとの違い、命名規則、実践例、初心者が間違えやすいポイントまで、わかりやすく解説します。

1. C# constantsとは?まず押さえたい基本

1-1. constantsはC#で「定数」を意味する検索語

「C# constants」とは、C#における「定数」を指す言葉としてよく使われます。

ただし、C#にconstantsというキーワードがあるわけではありません。C#で実際に使うキーワードは、主にconstreadonlyです。

C#
const double Pi = 3.14159;

この例では、Piという名前の定数を定義しています。

定数とは、プログラムの実行中に値を変更しない前提で使う値のことです。C#では、完全にコンパイル時に決まる値にはconstを使い、実行時に初期化したい値にはreadonlystatic readonlyを使います。

1-2. C#で定数を扱う主な方法はconst・readonly・static readonly

C#で「変更しない値」を扱う代表的な方法は、次の3つです。

C#
const int MaxCount = 100;

readonly int UserId;

static readonly string AppName = "SampleApp";

constは、コンパイル時に値が決まっている定数です。数値や文字列など、あらかじめ固定できる値に使います。

readonlyは、フィールドに対して使うキーワードです。宣言時またはコンストラクタ内で値を代入でき、その後は変更できません。

static readonlyは、クラス全体で共有される読み取り専用フィールドです。実行時に決まる値や、外部に公開する定数的な値によく使われます。

1-3. 変数と定数の違い

変数は、プログラムの途中で値を変更できます。

C#
int count = 10;
count = 20;

このコードでは、countに最初は10を代入し、その後20に変更しています。

一方、constで宣言した定数は、後から値を変更できません。

C#
const int MaxCount = 100;

// コンパイルエラー
MaxCount = 200;

定数は「この値は変わらない」という意図をコード上で明確に示すために使います。

たとえば、最大文字数を表すMaxNameLengthがプログラム中で突然変更されると、処理の意味がわかりにくくなります。定数にしておけば、「この値は固定である」と読み手に伝えられます。

1-4. 定数を使うメリット

定数を使う主なメリットは、コードの可読性と保守性が上がることです。

次のように数値を直接書くと、その20が何を意味しているのかわかりにくくなります。

C#
if (userName.Length > 20)
{
Console.WriteLine("ユーザー名が長すぎます。");
}

このような値は「マジックナンバー」と呼ばれます。意味のある名前を付けて定数化すると、コードの意図がわかりやすくなります。

C#
const int MaxUserNameLength = 20;

if (userName.Length > MaxUserNameLength)
{
Console.WriteLine("ユーザー名が長すぎます。");
}

定数を使うことで、次のような利点があります。

  • 値の意味がわかりやすくなる

  • 同じ値を複数箇所に書かずに済む

  • 値を変更するときに修正箇所を減らせる

  • タイプミスや修正漏れを防ぎやすい

  • コードの意図を明確にできる

2. C#のconstとは?基本構文と使い方

2-1. constの基本構文

C#で定数を定義するには、constキーワードを使います。

基本構文は次のとおりです。

C#
const  定数名 = ;

たとえば、整数の定数を定義する場合は次のように書きます。

C#
const int MaxCount = 100;

文字列の定数であれば、次のように書きます。

C#
const string AppName = "SampleApp";

constで定義した値は、宣言後に変更できません。

C#
const int TaxRate = 10;

// コンパイルエラー
TaxRate = 8;

定数は、プログラムの中で何度も使う固定値に名前を付けるときに便利です。

2-2. constで宣言できる型

constで宣言できる型には制限があります。代表的なものは次のとおりです。

C#
const int MaxCount = 100;
const double Pi = 3.14159;
const decimal TaxRate = 0.10m;
const bool IsEnabled = true;
const char Separator = ',';
const string Message = "Hello";

主に、数値型、boolcharstring、列挙型などがconstで使えます。

C#
enum UserRole
{
Admin,
Member,
Guest
}

const UserRole DefaultRole = UserRole.Member;

一方で、DateTimeや配列、通常のオブジェクトなどはconstにできません。

C#
// コンパイルエラー
const DateTime CreatedAt = DateTime.Now;

// コンパイルエラー
const int[] Numbers = new int[] { 1, 2, 3 };

constにできるのは、コンパイル時に値が完全に決まるものだけです。

2-3. constをクラス内・メソッド内で使う例

constは、クラスの中でフィールドのように定義できます。

C#
class UserValidator
{
public const int MaxNameLength = 20;

public bool IsValidName(string name)
{
return name.Length <= MaxNameLength;
}
}

この例では、MaxNameLengthをクラス内の定数として定義しています。

また、メソッド内のローカル定数として使うこともできます。

C#
void PrintPrice(int price)
{
const decimal TaxRate = 0.10m;

decimal tax = price * TaxRate;
Console.WriteLine($"税額: {tax}");
}

メソッド内でしか使わない固定値であれば、ローカル定数として定義しても問題ありません。

複数のメソッドで使う値ならクラス内に定義し、そのメソッドだけで使う値ならメソッド内に定義する、と考えるとわかりやすいです。

2-4. constは宣言時に必ず値を代入する

constは、宣言時に必ず値を代入する必要があります。

C#
const int MaxCount = 100;

次のように、値を入れずに宣言することはできません。

C#
// コンパイルエラー
const int MaxCount;

また、後から値を代入することもできません。

C#
// コンパイルエラー
const int MaxCount;
MaxCount = 100;

constはコンパイル時に値が決まっている必要があるため、宣言と同時に値を指定する必要があります。

2-5. constは暗黙的にstatic扱いになる

クラス内で定義したconstは、暗黙的にstatic扱いになります。

C#
class AppSettings
{
public const string AppName = "SampleApp";
}

この定数は、インスタンスを作らずにクラス名から参照できます。

C#
Console.WriteLine(AppSettings.AppName);

次のように、newでインスタンスを作る必要はありません。

C#
var settings = new AppSettings();

// constはインスタンスの値というより、クラスに属する固定値として扱われる
Console.WriteLine(AppSettings.AppName);

また、conststaticを付けて書く必要はありません。C#ではconst自体が静的な定数として扱われるためです。

C#
class Sample
{
// 正しい
public const int MaxCount = 100;

// 書かない
// public static const int MaxCount = 100;
}

3. constで使える値・使えない値

3-1. 数値・文字列・boolなどの定数

constでは、コンパイル時に確定できる数値や文字列、真偽値などを定義できます。

C#
const int MaxRetryCount = 3;
const double CircleRatio = 3.14159;
const decimal TaxRate = 0.10m;
const string DefaultLanguage = "ja-JP";
const bool IsDebugMode = false;

このような値は、プログラムを実行する前から値が明確に決まっています。

たとえば、最大リトライ回数や固定のメッセージ、既定の文字列などはconstの候補になります。

C#
const string RequiredMessage = "この項目は必須です。";
const int MaxPasswordLength = 64;

ただし、「今の日時」や「設定ファイルから読み込む値」のように、実行時にならないと決まらない値はconstにできません。

3-2. コンパイル時に決まる値だけ指定できる

constに指定できるのは、コンパイル時に決まる値だけです。

C#
const int BasePrice = 1000;
const int TaxIncludedPrice = BasePrice + 100;

この例では、BasePrice100もコンパイル時にわかる値なので、TaxIncludedPriceconstとして定義できます。

一方、メソッドの戻り値や実行時に取得する値はconstにできません。

C#
int GetMaxCount()
{
return 100;
}

// コンパイルエラー
const int MaxCount = GetMaxCount();

たとえGetMaxCount()が常に100を返すとしても、メソッド呼び出しは実行時の処理です。そのためconstには使えません。

3-3. DateTimeや配列をconstにできない理由

DateTimeは構造体ですが、constで定義できる型ではありません。

C#
// コンパイルエラー
const DateTime StartDate = new DateTime(2026, 1, 1);

DateTime.Nowも、実行するタイミングによって値が変わるため、当然constにはできません。

C#
// コンパイルエラー
const DateTime Now = DateTime.Now;

このような場合は、static readonlyを使います。

C#
static readonly DateTime StartDate = new DateTime(2026, 1, 1);
static readonly DateTime CreatedAt = DateTime.Now;

配列もconstにはできません。

C#
// コンパイルエラー
const int[] Numbers = { 1, 2, 3 };

配列はオブジェクトとして扱われ、要素の中身を変更できるため、constには向いていません。配列のような値をクラス全体で共有したい場合は、static readonlyを使うことがあります。

C#
static readonly int[] Numbers = { 1, 2, 3 };

ただし、static readonlyにしても配列の中身までは完全に保護されません。

C#
Numbers[0] = 99;

配列の参照は変更できなくても、配列の要素は変更できてしまいます。変更されたくないコレクションを扱う場合は、読み取り専用コレクションなども検討しましょう。

3-4. 計算式をconstに使えるケース

constには、単純な値だけでなく、コンパイル時に評価できる計算式も使えます。

C#
const int MinutesPerHour = 60;
const int SecondsPerMinute = 60;
const int SecondsPerHour = MinutesPerHour * SecondsPerMinute;

この例では、すべての値がコンパイル時に決まるため、SecondsPerHourconstにできます。

文字列の結合も、定数同士であれば使えます。

C#
const string AppName = "Sample";
const string Version = "1.0";
const string DisplayName = AppName + " v" + Version;

ただし、実行時にしか決まらない値を含む式は使えません。

C#
string userName = "Taro";

// コンパイルエラー
const string Message = "Hello, " + userName;

userNameは変数であり、実行時に値が変わる可能性があるため、constには使えません。

3-5. よくあるコンパイルエラーと対処法

constでよくあるエラーの1つは、実行時に決まる値を指定してしまうことです。

C#
// コンパイルエラー
const int MaxCount = int.Parse("100");

int.Parse("100")は結果として100になりますが、メソッド呼び出しなのでコンパイル時定数ではありません。

この場合は、直接値を書くか、readonlyまたはstatic readonlyを使います。

C#
const int MaxCount = 100;

// または
static readonly int MaxCountFromText = int.Parse("100");

DateTime.Nowを使おうとするケースもよくあります。

C#
// コンパイルエラー
const DateTime CreatedAt = DateTime.Now;

この場合は、次のように書きます。

C#
static readonly DateTime CreatedAt = DateTime.Now;

また、後から代入しようとするのもエラーです。

C#
// コンパイルエラー
const int MaxCount;
MaxCount = 100;

constは必ず宣言時に値を代入します。

C#
const int MaxCount = 100;

4. constとreadonlyの違い

4-1. constはコンパイル時定数、readonlyは実行時に初期化できる定数

constreadonlyは、どちらも「変更しない値」を表すために使われます。しかし、仕組みは大きく異なります。

constはコンパイル時に値が決まる定数です。

C#
const int MaxCount = 100;

一方、readonlyは実行時に値を設定できる読み取り専用フィールドです。

C#
readonly int maxCount;

public Sample(int count)
{
maxCount = count;
}

readonlyは、コンストラクタで値を代入できます。そのため、インスタンスごとに違う値を持たせることもできます。

C#
class User
{
public readonly int Id;

public User(int id)
{
Id = id;
}
}

この例では、Userインスタンスごとに異なるIdを設定できますが、一度コンストラクタで代入した後は変更できません。

4-2. readonlyの基本構文

readonlyはフィールドに対して使います。

C#
class Sample
{
readonly int maxCount = 100;
}

アクセス修飾子を付けることもできます。

C#
class Sample
{
public readonly int MaxCount = 100;
private readonly string name = "default";
}

readonlyは、宣言時に値を代入するか、コンストラクタ内で代入できます。

C#
class Sample
{
private readonly int maxCount;

public Sample()
{
maxCount = 100;
}
}

通常のメソッド内で再代入することはできません。

C#
class Sample
{
private readonly int maxCount;

public Sample()
{
maxCount = 100;
}

public void Change()
{
// コンパイルエラー
maxCount = 200;
}
}

4-3. readonlyはコンストラクタで値を代入できる

readonlyの大きな特徴は、コンストラクタで値を代入できることです。

C#
class Product
{
public readonly string Code;

public Product(string code)
{
Code = code;
}
}

この場合、Productを作るときに商品コードを指定できます。

C#
var productA = new Product("A001");
var productB = new Product("B002");

Console.WriteLine(productA.Code); // A001
Console.WriteLine(productB.Code); // B002

Codeはインスタンスごとに異なりますが、作成後には変更できません。

このように、実行時に値を決めたいが、その後は変更したくない場合にreadonlyが役立ちます。

4-4. constとreadonlyの使い分け

constreadonlyの使い分けは、値がいつ決まるかで考えるとわかりやすいです。

constが向いているのは、次のような値です。

C#
const int DaysInWeek = 7;
const int MaxRetryCount = 3;
const string DefaultMessage = "処理が完了しました。";

これらはコンパイル時に完全に決まる値です。

一方、readonlyが向いているのは、実行時に値を決めたい場合です。

C#
class AppConfig
{
public readonly string ConnectionString;

public AppConfig(string connectionString)
{
ConnectionString = connectionString;
}
}

設定ファイル、環境変数、ユーザー入力、現在日時など、実行時に決まる値はconstではなくreadonlystatic readonlyを使います。

4-5. 変更される可能性がある値はreadonlyを選ぶべき理由

constはコンパイル時定数なので、他のアセンブリから参照される場合に注意が必要です。

たとえば、ライブラリ側で次のような定数を公開したとします。

C#
public const decimal TaxRate = 0.10m;

別のアプリケーションがこの値を参照してコンパイルすると、0.10mという値がアプリケーション側に埋め込まれることがあります。

その後、ライブラリ側で値を変更しても、

C#
public const decimal TaxRate = 0.08m;

参照側のアプリケーションを再コンパイルしない限り、古い値を使い続ける可能性があります。

そのため、将来的に変更される可能性がある値を外部に公開する場合は、constよりもstatic readonlyを検討したほうが安全です。

C#
public static readonly decimal TaxRate = 0.10m;

税率、手数料、設定値、バージョン番号など、将来変わる可能性がある値は、安易にpublic constにしないようにしましょう。

5. constとstatic readonlyの違い

5-1. static readonlyとは

static readonlyは、クラスに属する読み取り専用フィールドです。

C#
class AppSettings
{
public static readonly string AppName = "SampleApp";
}

staticなので、インスタンスを作らずにクラス名から参照できます。

C#
Console.WriteLine(AppSettings.AppName);

readonlyなので、基本的には宣言時または静的コンストラクタでのみ代入できます。

C#
class AppSettings
{
public static readonly DateTime StartedAt;

static AppSettings()
{
StartedAt = DateTime.Now;
}
}

このように、static readonlyは実行時に値を決めたいクラス共通の値に向いています。

5-2. const・readonly・static readonlyの比較表

constreadonlystatic readonlyの違いを整理すると、次のようになります。

種類値が決まるタイミング再代入static扱い主な用途
constコンパイル時不可暗黙的にstatic絶対に変わらない固定値
readonly実行時宣言時・コンストラクタ内のみ可インスタンスごとインスタンス作成時に決める値
static readonly実行時宣言時・静的コンストラクタ内のみ可staticクラス共通の読み取り専用値

たとえば、曜日の数のように普遍的な値はconstに向いています。

C#
public const int DaysInWeek = 7;

インスタンスごとに異なるIDはreadonlyに向いています。

C#
public readonly int UserId;

実行時に生成するクラス共通の値はstatic readonlyに向いています。

C#
public static readonly Guid ApplicationId = Guid.NewGuid();

5-3. static readonlyが向いているケース

static readonlyは、次のようなケースに向いています。

C#
public static readonly DateTime ServiceStartDate = new DateTime(2026, 1, 1);
public static readonly Guid SystemId = Guid.NewGuid();
public static readonly string ConnectionString = LoadConnectionString();

DateTimeGuid、配列、オブジェクト、設定ファイルから読み込む値などは、constでは扱えません。

そのため、クラス全体で共有したいが、実行時に初期化したい値にはstatic readonlyを使います。

C#
class FileSettings
{
public static readonly string LogDirectory = Path.Combine(AppContext.BaseDirectory, "logs");
}

Path.Combineはメソッド呼び出しなのでconstには使えませんが、static readonlyなら使用できます。

5-4. public constを使うときの注意点

public constは外部から参照できる定数を定義するときに使えます。

C#
public class ApiSettings
{
public const string Version = "v1";
}

ただし、public constは慎重に使うべきです。

理由は、参照側のコードに値が埋め込まれる可能性があるためです。ライブラリや共通部品として公開している場合、public constの値を変更しても、利用側が再コンパイルしないと変更が反映されないことがあります。

次のような値は、将来変わる可能性があります。

C#
public const decimal TaxRate = 0.10m;
public const int MaxUploadSize = 10485760;
public const string ApiVersion = "v1";

一見固定に見えても、業務要件や仕様変更で変わる可能性があるなら、static readonlyを検討しましょう。

C#
public static readonly decimal TaxRate = 0.10m;
public static readonly int MaxUploadSize = 10485760;
public static readonly string ApiVersion = "v1";

5-5. ライブラリやAPIで定数を公開する場合の選び方

ライブラリやAPIで値を公開する場合は、「その値が本当に永遠に変わらないか」を考えることが大切です。

数学的な定数や仕様上絶対に変わらない値であれば、public constでも問題ない場合があります。

C#
public const int DaysInWeek = 7;

しかし、業務上のルール、APIのバージョン、制限値、料金、税率、メッセージなどは変わる可能性があります。

C#
public static readonly int MaxLoginAttempts = 5;
public static readonly string ApiBasePath = "/api/v1";

外部に公開する値で、将来的に変更の可能性が少しでもあるなら、static readonlyを選ぶと安全です。

また、値を完全に外部設定として管理したい場合は、定数ではなく設定ファイルや環境変数で管理する方法も検討しましょう。

6. C# constantsの命名規則

6-1. C#の定数名はPascalCaseが一般的

C#では、定数名にはPascalCaseがよく使われます。

C#
const int MaxRetryCount = 3;
const string DefaultUserName = "Guest";
const decimal TaxRate = 0.10m;

PascalCaseとは、単語の先頭を大文字にしてつなげる書き方です。

C#
MaxRetryCount
DefaultUserName
ErrorMessage

C#では、クラス名、メソッド名、プロパティ名、定数名などにPascalCaseがよく使われます。

6-2. C#ではSNAKE_CASEよりPascalCaseが推奨されやすい

他の言語では、定数名をすべて大文字のSNAKE_CASEで書くことがあります。

C#
MAX_RETRY_COUNT
DEFAULT_USER_NAME
ERROR_MESSAGE

しかし、C#では一般的にPascalCaseが使われることが多いです。

C#
MaxRetryCount
DefaultUserName
ErrorMessage

もちろん、プロジェクトやチームによってルールが決まっている場合は、そのルールに従うべきです。

ただ、C#らしい書き方を意識するなら、定数名もPascalCaseにするのが自然です。

6-3. private constとpublic constの命名例

private constでもpublic constでも、基本的にはPascalCaseで書くことが多いです。

C#
class UserService
{
private const int MaxLoginAttempts = 5;
private const string DefaultRole = "Member";

public const int MaxUserNameLength = 20;
public const string GuestUserName = "Guest";
}

ただし、privateなフィールドではアンダースコア始まりの命名を使うチームもあります。

C#
private const int _maxLoginAttempts = 5;

とはいえ、C#の定数では次のように書くほうが一般的で読みやすいでしょう。

C#
private const int MaxLoginAttempts = 5;

大切なのは、プロジェクト内で命名ルールを統一することです。同じプロジェクト内でMaxCountMAX_COUNTが混在していると、コードの印象がばらついてしまいます。

6-4. 意味が伝わる定数名の付け方

定数名は、値そのものよりも「何のための値か」が伝わる名前にすることが大切です。

たとえば、次の名前は少し抽象的です。

C#
const int Count = 3;
const int Length = 20;
const string Message = "エラーが発生しました。";

これだけでは、何の回数、何の長さ、何のメッセージなのかわかりません。

より具体的にすると、読みやすくなります。

C#
const int MaxRetryCount = 3;
const int MaxUserNameLength = 20;
const string ValidationErrorMessage = "エラーが発生しました。";

定数名を付けるときは、次のような観点で考えるとよいでしょう。

  • 何の値か

  • どこで使う値か

  • 上限なのか下限なのか

  • 既定値なのか

  • エラー用なのか表示用なのか

たとえば、最大値ならMax、最小値ならMin、既定値ならDefault、エラーメッセージならErrorMessageを含めると意味が伝わりやすくなります。

C#
const int MinPasswordLength = 8;
const int MaxPasswordLength = 64;
const string DefaultLanguage = "ja-JP";
const string RequiredFieldErrorMessage = "必須項目です。";

6-5. マジックナンバーを定数化する命名例

マジックナンバーとは、コード内に直接書かれた意味のわかりにくい数値のことです。

C#
if (password.Length < 8)
{
Console.WriteLine("パスワードが短すぎます。");
}

この8は、パスワードの最小文字数を意味しています。しかし、コードを読んだだけではすぐに意図が伝わらない場合があります。

定数化すると、意味が明確になります。

C#
const int MinPasswordLength = 8;

if (password.Length < MinPasswordLength)
{
Console.WriteLine("パスワードが短すぎます。");
}

他にも、次のような定数名が考えられます。

C#
const int MaxRetryCount = 3;
const int MaxUploadFileSizeMb = 10;
const int SessionTimeoutMinutes = 30;
const decimal TaxRate = 0.10m;

値に名前を付けることで、コードが「何をしているのか」だけでなく、「なぜその値を使っているのか」も伝わりやすくなります。

7. constの実践例

7-1. 消費税率をconstで定義する例

消費税率のような値は、計算処理で何度も使われることがあります。

C#
class PriceCalculator
{
private const decimal TaxRate = 0.10m;

public decimal CalculateTax(decimal price)
{
return price * TaxRate;
}

public decimal CalculateTotalPrice(decimal price)
{
return price + CalculateTax(price);
}
}

このようにTaxRateとして定数化すると、0.10mが何を意味しているのか明確になります。

ただし、税率は将来変わる可能性があります。そのため、実務ではconstではなくstatic readonlyや設定ファイルで管理したほうがよい場合もあります。

C#
class PriceCalculator
{
private static readonly decimal TaxRate = 0.10m;
}

「絶対に変わらない値か」「業務ルールとして変わる可能性がある値か」を考えて選びましょう。

7-2. エラーメッセージをconst stringで定義する例

固定のエラーメッセージは、const stringで定義できます。

C#
class ErrorMessages
{
public const string RequiredName = "名前は必須です。";
public const string InvalidEmail = "メールアドレスの形式が正しくありません。";
public const string PasswordTooShort = "パスワードが短すぎます。";
}

使う側は、次のように参照できます。

C#
Console.WriteLine(ErrorMessages.RequiredName);

複数の場所で同じメッセージを使う場合、文字列を毎回直接書くよりも、定数としてまとめたほうが管理しやすくなります。

C#
if (string.IsNullOrEmpty(name))
{
return ErrorMessages.RequiredName;
}

ただし、多言語対応が必要なアプリケーションでは、メッセージをconst stringで固定するのではなく、リソースファイルなどで管理することもあります。

7-3. 最大文字数・上限値をconstで定義する例

入力チェックでは、最大文字数や最小文字数を定数化すると読みやすくなります。

C#
class UserValidator
{
private const int MinPasswordLength = 8;
private const int MaxUserNameLength = 20;

public bool IsValidUserName(string userName)
{
return userName.Length <= MaxUserNameLength;
}

public bool IsValidPassword(string password)
{
return password.Length >= MinPasswordLength;
}
}

このコードでは、820という数値を直接書く代わりに、意味のある名前を付けています。

次のようなコードよりも、

C#
return password.Length >= 8;

次のコードのほうが、意図が明確です。

C#
return password.Length >= MinPasswordLength;

仕様変更でパスワードの最小文字数が変わった場合も、定数の値を変更するだけで対応しやすくなります。

7-4. 設定値をreadonlyで扱う例

設定ファイルや環境変数から読み込む値は、constでは扱えません。実行時に値が決まるためです。

このような場合は、readonlyを使います。

C#
class MailSettings
{
public readonly string SmtpServer;
public readonly int Port;

public MailSettings(string smtpServer, int port)
{
SmtpServer = smtpServer;
Port = port;
}
}

使う側は、次のように設定値を渡します。

C#
var settings = new MailSettings("smtp.example.com", 587);

Console.WriteLine(settings.SmtpServer);
Console.WriteLine(settings.Port);

SmtpServerPortは、インスタンス作成時に決まり、その後は変更できません。

アプリケーション全体で共有する設定値なら、static readonlyを使うこともあります。

C#
class AppSettings
{
public static readonly string EnvironmentName =
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
}

Environment.GetEnvironmentVariableは実行時の処理なので、constではなくstatic readonlyを使います。

7-5. 定数クラスを作る場合のサンプル

定数が複数ある場合、用途ごとにクラスへまとめることがあります。

C#
public static class AppConstants
{
public const int MaxRetryCount = 3;
public const int MaxUserNameLength = 20;
public const string DefaultLanguage = "ja-JP";
}

使う側は、次のように参照できます。

C#
Console.WriteLine(AppConstants.MaxRetryCount);
Console.WriteLine(AppConstants.DefaultLanguage);

エラーメッセージをまとめるなら、次のように分けてもよいでしょう。

C#
public static class ErrorMessages
{
public const string RequiredField = "必須項目です。";
public const string InvalidEmail = "メールアドレスの形式が正しくありません。";
}

ただし、すべての定数を1つの巨大なConstantsクラスに詰め込むと、逆に管理しづらくなります。

C#
public static class Constants
{
// ユーザー関連
public const int MaxUserNameLength = 20;

// 商品関連
public const int MaxProductNameLength = 100;

// メール関連
public const int MaxMailSubjectLength = 200;
}

定数が増えてきたら、用途ごとにクラスを分けると読みやすくなります。

C#
public static class UserConstants
{
public const int MaxUserNameLength = 20;
}

public static class ProductConstants
{
public const int MaxProductNameLength = 100;
}

public static class MailConstants
{
public const int MaxSubjectLength = 200;
}

8. C# constantsで初心者が間違えやすいポイント

8-1. constに後から値を代入しようとする

constは宣言時に値を代入しなければなりません。後から代入することはできません。

C#
// コンパイルエラー
const int MaxCount;
MaxCount = 100;

正しくは、次のように宣言と同時に値を指定します。

C#
const int MaxCount = 100;

後から値を決めたい場合は、constではなくreadonlyを使います。

C#
class Sample
{
private readonly int maxCount;

public Sample(int count)
{
maxCount = count;
}
}

constは「最初から値が決まっているもの」に使う、と覚えておくとよいでしょう。

8-2. constにDateTime.Nowを指定しようとする

初心者がよく間違える例として、DateTime.Nowconstにしようとするケースがあります。

C#
// コンパイルエラー
const DateTime Now = DateTime.Now;

DateTime.Nowは、プログラムを実行した瞬間の日時を返します。つまり、実行時に値が決まります。

constはコンパイル時に値が決まっていなければならないため、DateTime.Nowは使えません。

この場合は、static readonlyを使います。

C#
static readonly DateTime StartedAt = DateTime.Now;

特定の日付を固定したい場合でも、DateTimeconstにできません。

C#
// コンパイルエラー
const DateTime ReleaseDate = new DateTime(2026, 1, 1);

この場合もstatic readonlyを使います。

C#
static readonly DateTime ReleaseDate = new DateTime(2026, 1, 1);

8-3. public constを安易に使う

public constは便利ですが、外部に公開する値として使う場合は注意が必要です。

C#
public const int MaxUploadSize = 10485760;

この値が別のプロジェクトから参照される場合、参照側に値が埋め込まれる可能性があります。

そのため、ライブラリ側で値を変更しても、参照側を再コンパイルしないと古い値のままになることがあります。

将来変わる可能性がある値は、public constではなくpublic static readonlyを検討しましょう。

C#
public static readonly int MaxUploadSize = 10485760;

特に、業務ルール、制限値、料金、税率、APIバージョンなどは変わる可能性があるため、constにする前に慎重に考える必要があります。

8-4. 何でも定数化してコードを読みにくくする

定数化は便利ですが、何でも定数にすればよいわけではありません。

たとえば、次のようなコードを考えてみます。

C#
const int One = 1;
const int Two = 2;

int nextPage = currentPage + One;

この場合、Oneという定数にしても、コードがわかりやすくなるとは限りません。

単に数値の1を使ったほうが自然な場合もあります。

C#
int nextPage = currentPage + 1;

定数化すべきなのは、値に業務的な意味や仕様上の意味がある場合です。

C#
const int DefaultPageSize = 20;
const int MaxLoginAttempts = 5;
const int SessionTimeoutMinutes = 30;

定数化の目的は、コードを読みやすくすることです。定数が増えすぎて逆に読みにくくなるなら、本末転倒です。

8-5. const・readonly・static readonlyを混同する

constreadonlystatic readonlyは似ていますが、使う場面が異なります。

constは、コンパイル時に決まる固定値です。

C#
const int MaxCount = 100;

readonlyは、インスタンスごとに持つ読み取り専用フィールドです。

C#
class User
{
public readonly int Id;

public User(int id)
{
Id = id;
}
}

static readonlyは、クラス全体で共有する読み取り専用フィールドです。

C#
class AppInfo
{
public static readonly DateTime StartedAt = DateTime.Now;
}

どれを使うか迷った場合は、次のように考えるとよいでしょう。

C#
// コンパイル時に決まる
const int MaxCount = 100;

// インスタンスごとに決まる
readonly int userId;

// クラス全体で共有し、実行時に決まる
static readonly DateTime StartedAt = DateTime.Now;

9. C# constantsのベストプラクティス

9-1. 絶対に変わらない値はconstを使う

constは、絶対に変わらない値に使うのが基本です。

C#
public const int DaysInWeek = 7;
public const int MonthsInYear = 12;

このような値は、将来的にも変わる可能性がほとんどありません。

また、プログラム内だけで使う固定の文字列や、仕様として明確に固定されている値にも使えます。

C#
private const string CsvExtension = ".csv";
private const char CsvSeparator = ',';

ただし、「現在は固定だが、将来的に変更される可能性がある値」はconstにしないほうが安全です。

9-2. 将来変わる可能性がある値はreadonlyまたはstatic readonlyを使う

業務要件や設定によって変わる可能性がある値は、readonlystatic readonlyを使いましょう。

C#
public static readonly decimal TaxRate = 0.10m;
public static readonly int MaxUploadSize = 10485760;

特に、外部に公開する値や、別プロジェクトから参照される値は注意が必要です。

アプリケーション起動時に設定ファイルから読み込む場合は、次のような形になります。

C#
class AppConfig
{
public readonly string ApiBaseUrl;

public AppConfig(string apiBaseUrl)
{
ApiBaseUrl = apiBaseUrl;
}
}

値が実行時に決まるなら、constではなくreadonlyを使うのが自然です。

9-3. 外部公開する値はstatic readonlyを検討する

ライブラリや共通プロジェクトで値を公開する場合は、public constよりもpublic static readonlyを検討しましょう。

C#
public static class ApiSettings
{
public static readonly string Version = "v1";
public static readonly int TimeoutSeconds = 30;
}

static readonlyであれば、constのように参照側へ値が直接埋め込まれる問題を避けやすくなります。

もちろん、すべてのpublic constが悪いわけではありません。完全に普遍的で変わらない値であれば、public constも選択肢になります。

C#
public const int DaysInWeek = 7;

しかし、実務では「変わらないと思っていた値が変わる」ことがよくあります。迷った場合は、外部公開する値にはstatic readonlyを使うほうが安全です。

9-4. マジックナンバーを避けて可読性を高める

コード内に意味のわからない数値や文字列を直接書くと、後から読んだときに意図がわかりにくくなります。

C#
if (loginFailedCount >= 5)
{
LockAccount();
}

この5が何を意味するのか、コードだけでは少しわかりにくいです。

定数化すると、意図が明確になります。

C#
const int MaxLoginAttempts = 5;

if (loginFailedCount >= MaxLoginAttempts)
{
LockAccount();
}

文字列も同じです。

C#
if (status == "ACTIVE")
{
// 処理
}

定数化すると、タイプミスを防ぎやすくなります。

C#
const string ActiveStatus = "ACTIVE";

if (status == ActiveStatus)
{
// 処理
}

ただし、状態値のようなものは、文字列定数よりもenumを使ったほうがよい場合もあります。

C#
enum UserStatus
{
Active,
Inactive,
Suspended
}

目的に応じて、constenum、設定ファイルなどを使い分けましょう。

9-5. 定数は用途ごとに整理する

定数が増えてくると、管理が難しくなります。

すべてを1つのクラスにまとめると、どこに何があるのかわかりにくくなることがあります。

C#
public static class Constants
{
public const int MaxUserNameLength = 20;
public const int MaxProductNameLength = 100;
public const string RequiredFieldMessage = "必須項目です。";
public const string DefaultCurrency = "JPY";
}

小規模なアプリケーションなら問題ない場合もありますが、規模が大きくなると整理が必要です。

用途ごとに分けると、見通しがよくなります。

C#
public static class UserConstants
{
public const int MaxUserNameLength = 20;
public const int MinPasswordLength = 8;
}

public static class ProductConstants
{
public const int MaxProductNameLength = 100;
}

public static class ErrorMessages
{
public const string RequiredField = "必須項目です。";
}

また、そのクラス内でしか使わない定数は、無理に共通クラスへ移動せず、使う場所の近くに置いたほうが読みやすいこともあります。

C#
class UserValidator
{
private const int MaxUserNameLength = 20;

public bool IsValid(string userName)
{
return userName.Length <= MaxUserNameLength;
}
}

定数は「使う場所」「用途」「公開範囲」を意識して整理しましょう。

10. C# constantsに関するよくある質問

10-1. C#にconstantsというキーワードはある?

C#にconstantsというキーワードはありません。

C#で定数を定義するときは、constキーワードを使います。

C#
const int MaxCount = 100;

また、実行時に初期化したい読み取り専用の値には、readonlystatic readonlyを使います。

C#
readonly int userId;
static readonly DateTime StartedAt = DateTime.Now;

「C# constants」と検索されることは多いですが、実際のコードではconstreadonlystatic readonlyを使い分けると理解しておきましょう。

10-2. constはstaticを付けなくても使える?

はい。クラス内のconstは暗黙的にstatic扱いになります。

C#
class AppSettings
{
public const string AppName = "SampleApp";
}

そのため、インスタンスを作らずにクラス名から参照できます。

C#
Console.WriteLine(AppSettings.AppName);

conststaticを付けて書く必要はありません。

C#
// 正しい
public const int MaxCount = 100;

// 書かない
// public static const int MaxCount = 100;

10-3. constとreadonlyはどちらを使えばいい?

値がコンパイル時に決まり、将来変わる可能性がほとんどないならconstを使います。

C#
const int DaysInWeek = 7;

実行時に値を決めたい場合や、将来変更される可能性がある場合はreadonlystatic readonlyを使います。

C#
readonly int userId;

static readonly DateTime StartedAt = DateTime.Now;

外部に公開する値で、将来変わる可能性がある場合は、public constよりもpublic static readonlyを検討するとよいでしょう。

10-4. constで配列やオブジェクトは定義できる?

基本的に、配列や通常のオブジェクトはconstで定義できません。

C#
// コンパイルエラー
const int[] Numbers = { 1, 2, 3 };

// コンパイルエラー
const object Value = new object();

配列やオブジェクトは実行時に生成されるため、constにはできません。

このような場合は、static readonlyを使います。

C#
static readonly int[] Numbers = { 1, 2, 3 };
static readonly object Value = new object();

ただし、配列をstatic readonlyにしても、配列の中身は変更できる点に注意が必要です。

C#
Numbers[0] = 99;

完全に変更されたくないデータを扱う場合は、読み取り専用コレクションや不変コレクションも検討しましょう。

10-5. 定数名は大文字にするべき?

C#では、定数名をすべて大文字にするよりも、PascalCaseで書くことが一般的です。

C#
const int MaxRetryCount = 3;
const string DefaultLanguage = "ja-JP";

他の言語では、次のような大文字のSNAKE_CASEが使われることもあります。

C#
const int MAX_RETRY_COUNT = 3;

しかし、C#ではMaxRetryCountのような書き方が自然です。

ただし、最終的にはプロジェクトやチームのコーディング規約に従うことが大切です。既存コードがSNAKE_CASEで統一されているなら、それに合わせたほうがよい場合もあります。

まとめ

C# constantsとは、C#における定数や変更しない値を扱う考え方を指す言葉です。実際のC#コードでは、主にconstreadonlystatic readonlyを使い分けます。

constは、コンパイル時に値が決まる定数に使います。

C#
const int MaxRetryCount = 3;
const string DefaultMessage = "処理が完了しました。";

数値、文字列、boolchar、列挙型など、コンパイル時に確定できる値に向いています。

一方、DateTime.Now、配列、オブジェクト、設定ファイルから読み込む値などはconstにできません。そのような場合は、readonlystatic readonlyを使います。

C#
readonly int userId;
static readonly DateTime StartedAt = DateTime.Now;

特に、外部に公開する値や将来変更される可能性がある値は、public constではなくpublic static readonlyを検討するのが安全です。

また、定数名はC#ではPascalCaseが一般的です。

C#
const int MaxUserNameLength = 20;
const int MinPasswordLength = 8;
const string RequiredFieldMessage = "必須項目です。";

定数を適切に使うことで、マジックナンバーを避け、コードの意味を明確にできます。ただし、何でも定数化すればよいわけではありません。値の意味、変更可能性、公開範囲、使う場所を考えて、constreadonlystatic readonlyを使い分けましょう。