C#(CSharp)の命名規則を完全解説|クラス・メソッド・変数名の付け方と実例

はじめに

C#で読みやすく保守しやすいコードを書くには、処理内容だけでなく、クラス名・メソッド名・変数名などの「命名」が重要です。

たとえば、次の2つは同じような処理を表しています。

C#
var d = DateTime.Now;
var currentDateTime = DateTime.Now;

短いコードではどちらも理解できますが、処理が複雑になるほど、currentDateTimeのように意味が伝わる名前のほうが読みやすくなります。

C#の命名規則では、主に次の表記を使い分けます。

  • クラス名やメソッド名:PascalCase

  • ローカル変数や引数:camelCase

  • privateフィールド:_camelCase

  • インターフェイス:IPascalCase

ただし、命名規則の多くはC#コンパイラが強制する文法ではなく、開発者間でコードの一貫性を保つための慣習です。Microsoftの公式ガイドラインを基準にしつつ、既存プロジェクトやチームのルールを優先することが大切です。Microsoft Learn

この記事では、C#の命名規則をクラス・メソッド・変数・フィールド・定数などの対象別に、具体例を交えて解説します。

1. C#の命名規則とは?まず押さえるべき基本

1-1. 命名規則が必要な理由

命名規則とは、プログラム内のクラス、メソッド、変数などに名前を付けるときのルールです。

命名規則を統一する主な目的は、コードを読んだ人が名前を見るだけで、その要素の種類や役割を判断できるようにすることです。

たとえば、次の名前を見てみましょう。

C#
CustomerService
CalculateTotalPrice
customerName
_orderRepository

C#の一般的な命名規則を知っていれば、次のように推測できます。

  • CustomerService:クラスや型

  • CalculateTotalPrice:メソッド

  • customerName:ローカル変数または引数

  • _orderRepository:privateフィールド

命名規則が統一されていると、コードレビューや機能追加、バグ修正が行いやすくなります。複数人で開発する場合はもちろん、個人開発でも数か月後に自分のコードを読み直す際に役立ちます。

1-2. C#における「識別子」とは

識別子とは、プログラム内の要素を区別するために付ける名前です。

C#では、次のような名前が識別子に該当します。

C#
namespace SampleApp;

public class UserService
{
private readonly string _userName;

public string GetUserName()
{
return _userName;
}
}

この例では、次の文字列が識別子です。

  • SampleApp

  • UserService

  • _userName

  • GetUserName

C#の識別子は大文字と小文字を区別します。そのため、userNameUserNameは別の識別子です。

C#
string userName = "Sato";
string UserName = "Tanaka";

文法上は両方を宣言できる場合がありますが、見間違いや入力ミスの原因になるため、このような使い分けは避けるべきです。

識別子の先頭には、基本的に文字またはアンダースコアを使用します。2文字目以降には数字も使用できます。連続する2つのアンダースコアは、コンパイラが生成する識別子のために予約されているため、通常のコードでは避けます。Microsoft Learn

C#
// 使用できる名前
string userName;
string _userName;
string user2;

// 数字から始まるため使用できない
// string 2user;

1-3. コンパイルエラーになる名前と慣習上避けるべき名前の違い

C#の命名には、「文法上使用できない名前」と「使用できるが避けたほうがよい名前」があります。

数字から始まる識別子は文法違反です。

C#
// コンパイルエラー
// int 1stScore = 100;

C#の予約語も、そのままでは識別子として使えません。

C#
// コンパイルエラー
// string class = "A";

予約語の前に@を付ければ、識別子として使用できます。

C#
string @class = "A";

ただし、@classのような名前はコードを読みにくくします。外部データとのマッピングなど特別な事情がなければ、次のように別の単語へ置き換えるほうが適切です。

C#
string className = "A";

一方、次の名前はコンパイルできますが、意味が伝わりにくいため避けるべきです。

C#
int a;
string tmp;
decimal data;
UserService userService1;

コンパイルできるかどうかだけでなく、ほかの開発者が名前から役割を理解できるかを考えましょう。

1-4. C#の命名でよく使うPascalCase・camelCase・アンダースコアの違い

C#では、主にPascalCaseとcamelCaseを使います。

PascalCaseは、すべての単語の先頭を大文字にする形式です。

Customer
CustomerService
CalculateTotalPrice

クラス、構造体、列挙型、メソッド、プロパティ、イベントなどに使用します。

camelCaseは、最初の単語を小文字で始め、2語目以降の先頭を大文字にする形式です。

customer
customerName
totalPrice

ローカル変数やメソッドの引数などに使用します。

アンダースコア付きcamelCaseは、camelCaseの先頭に_を付ける形式です。

_customer
_customerName
_orderRepository

主にprivateインスタンスフィールドに使用します。

なお、単語を区切る目的でcustomer_nameのようなsnake_caseを使うのは、一般的なC#の命名規則ではありません。

2. C#の命名規則早見表

2-1. クラス・メソッド・変数などの命名ルール一覧

C#で一般的に使われる命名規則は次のとおりです。

対象基本ルール
名前空間PascalCaseCompany.Product.Services
クラスPascalCaseCustomerService
レコードPascalCaseCustomerAddress
構造体PascalCasePoint
インターフェイスI+PascalCaseIUserRepository
列挙型PascalCaseOrderStatus
列挙値PascalCaseProcessing
デリゲートPascalCaseMessageHandler
メソッドPascalCaseCalculateTotalPrice
非同期メソッドPascalCase+AsyncSaveAsync
プロパティPascalCaseCustomerName
イベントPascalCaseOrderCompleted
ローカル変数camelCasecustomerName
引数camelCasecustomerId
privateフィールド_+camelCase_customerRepository
private staticフィールドプロジェクト規則に従うs_cacheなど
定数PascalCaseMaxRetryCount
readonlyフィールドフィールドの規則に従う_defaultTimeout
ジェネリック型引数TまたはT+説明語TTEntity

Microsoftの現在のC#命名ガイドでは、型・名前空間・公開メンバーにPascalCase、引数やローカル変数にcamelCase、privateインスタンスフィールドに_camelCase、定数にPascalCaseを使う形式が示されています。Microsoft Learn+1

2-2. PascalCaseを使う名前

PascalCaseは、主に型や外部から見えるメンバーに使用します。

C#
public class OrderService
{
public decimal TaxRate { get; init; }

public event EventHandler? OrderCompleted;

public decimal CalculateTotalPrice()
{
return 0;
}
}

この例では、次の名前がPascalCaseです。

  • OrderService

  • TaxRate

  • OrderCompleted

  • CalculateTotalPrice

メソッドはアクセス修飾子に関係なく、通常はPascalCaseにします。

C#
private void ValidateOrder()
{
}

2-3. camelCaseを使う名前

camelCaseは、主にローカル変数と引数に使用します。

C#
public decimal CalculatePrice(decimal unitPrice, int quantity)
{
decimal totalPrice = unitPrice * quantity;
return totalPrice;
}

この例では、次の名前がcamelCaseです。

  • unitPrice

  • quantity

  • totalPrice

単語を並べるだけではなく、名前から値の意味が分かるようにすることが重要です。

C#
// 意味が曖昧
decimal value;

// 意味が具体的
decimal totalPrice;

2-4. アンダースコアを使う名前

一般的なC#コードでは、アンダースコアはprivateフィールドの接頭辞として使われます。

C#
public class OrderService
{
private readonly IOrderRepository _orderRepository;
private readonly ILogger<OrderService> _logger;

public OrderService(
IOrderRepository orderRepository,
ILogger<OrderService> logger)
{
_orderRepository = orderRepository;
_logger = logger;
}
}

引数とフィールドの名前が似ていても、アンダースコアによって区別できます。

C#
_orderRepository = orderRepository;

一方、次のように単語の区切りとしてアンダースコアを使う形式は、一般的なC#コードでは避けます。

C#
// C#では一般的ではない
string customer_name;
decimal total_price;

2-5. 大文字・小文字・略語の扱い

C#では大文字と小文字が区別されるため、表記の統一が重要です。

C#
string customerId;
string customerID;
string CustomerId;

この3つは別の識別子として扱われますが、同じスコープ周辺で混在させると読み間違いの原因になります。

略語は、広く認識されているものだけを使用するのが基本です。

C#
// 比較的理解しやすい
string customerId;
string imageUrl;
string htmlContent;

// 意味が分かりにくい
string cstId;
string imgU;
string hCnt;

従来の.NET設計ガイドラインでは、3文字以上の略語を通常の単語と同様に扱い、HtmlTagのように表記する考え方が示されています。2文字の略語にはIOStreamのような例外もあります。ただし、略語の表記は既存APIやプロジェクト内の慣習と一致させることが最優先です。Microsoft Learn

3. C#のクラス・型に関する命名規則

3-1. クラス名の付け方

クラス名にはPascalCaseを使用し、クラスが表す責務を名詞または名詞句で表現します。

C#
public class Customer
{
}

public class OrderService
{
}

public class PaymentValidator
{
}

クラス名を考えるときは、ManagerUtilityHelperなどの曖昧な単語を安易に使わないようにします。

C#
// 責務が曖昧
public class DataManager
{
}

// 責務が具体的
public class CustomerRepository
{
}

クラス名が長くなりすぎる場合は、名前の問題ではなく、クラスが複数の責務を抱えている可能性もあります。

C#
// 責務が多すぎる可能性がある
public class CustomerOrderPaymentNotificationManager
{
}

この場合は、次のようにクラスを分割できないか検討します。

C#
public class OrderService
{
}

public class PaymentService
{
}

public class NotificationService
{
}

3-2. インターフェイス名の付け方

インターフェイス名は、先頭に大文字のIを付け、その後をPascalCaseにします。

C#
public interface IUserRepository
{
}

public interface IEmailSender
{
}

public interface IOrderValidator
{
}

Iを付けることで、利用側からインターフェイスであることを判別しやすくなります。これは.NET API全体で広く使用されている規則です。Microsoft Learn

実装クラスは、先頭のIを外した名前にすることがあります。

C#
public interface IEmailSender
{
void Send(string address, string message);
}

public class EmailSender : IEmailSender
{
public void Send(string address, string message)
{
}
}

実装方式が複数ある場合は、違いを名前に含めます。

C#
public class SmtpEmailSender : IEmailSender
{
}

public class ConsoleEmailSender : IEmailSender
{
}

3-3. 構造体名の付け方

構造体名にもPascalCaseを使用します。

C#
public readonly struct Money
{
}

public readonly struct Point
{
}

public readonly struct DateRange
{
}

構造体名には、値そのものを表す名詞を使うと理解しやすくなります。

C#
public readonly record struct ProductCode(string Value);

Structという接尾辞は、通常は不要です。

C#
// 避けたい
public struct PointStruct
{
}

// 推奨
public struct Point
{
}

3-4. 列挙型(enum)名の付け方

列挙型名と列挙値にはPascalCaseを使用します。

C#
public enum OrderStatus
{
Pending,
Processing,
Shipped,
Canceled
}

通常の列挙型名には単数形を使用します。

C#
public enum PaymentMethod
{
CreditCard,
BankTransfer,
Cash
}

Flags属性を使い、複数の値を組み合わせる列挙型には複数形を使用します。

C#
[Flags]
public enum FilePermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}

通常の列挙型には単数名詞、フラグ列挙型には複数名詞を使うことが、MicrosoftのC#命名規則でも推奨されています。Microsoft Learn

3-5. 名前空間(namespace)の付け方

名前空間にはPascalCaseを使用し、組織名、製品名、機能名などを階層的に並べます。

C#
namespace ExampleCompany.Ecommerce.Orders;

一般的には、次のような構成にします。

会社名.製品名.機能名

例:

C#
namespace Contoso.Shop.Customers;
namespace Contoso.Shop.Orders;
namespace Contoso.Shop.Payments;

CommonMiscOthersなどの曖昧な名前空間を増やすと、クラスの配置基準が分かりにくくなります。

C#
// 曖昧
namespace SampleApp.Common;

// 役割が明確
namespace SampleApp.Validation;

3-6. ジェネリック型パラメーターの付け方

単純なジェネリック型パラメーターにはTを使用します。

C#
public class Cache<T>
{
}

複数の型パラメーターがある場合や、型の役割を説明する必要がある場合は、Tの後に説明語を付けます。

C#
public interface IRepository<TEntity>
{
}

public class Result<TValue, TError>
{
}

public delegate TOutput Converter<TInput, TOutput>(TInput input);

型制約がある場合は、制約内容が伝わる名前にすると理解しやすくなります。

C#
public class EntityRepository<TEntity>
where TEntity : IEntity
{
}

説明的な型パラメーターにはTを接頭辞として付ける方法が、公式ガイドラインでも示されています。Microsoft Learn

4. C#のメソッド・プロパティ・イベントの命名規則

4-1. メソッド名の付け方

メソッド名にはPascalCaseを使用し、基本的には処理を表す動詞または動詞句を使います。

C#
public void SaveOrder()
{
}

public decimal CalculateTotalPrice()
{
return 0;
}

public Customer FindCustomerById(int customerId)
{
throw new NotImplementedException();
}

よく使われる動詞には、次のようなものがあります。

処理名前の例
取得するGetCustomer
検索するFindCustomerSearchCustomers
作成するCreateOrder
保存するSaveOrder
更新するUpdateCustomer
削除するDeleteOrder
検証するValidateRequest
計算するCalculateTotalPrice
変換するConvertToDto
送信するSendEmail

ProcessHandleは便利ですが、何を処理するのかが分かる名前にします。

C#
// 曖昧
public void Process()
{
}

// 具体的
public void ProcessPayment()
{
}

4-2. 非同期メソッド名とAsyncサフィックス

非同期処理を表すメソッドには、通常Asyncサフィックスを付けます。

C#
public async Task SaveOrderAsync(Order order)
{
await _orderRepository.SaveAsync(order);
}

public async Task<Customer?> FindCustomerAsync(int customerId)
{
return await _customerRepository.FindAsync(customerId);
}

同期版と非同期版が並んでいる場合も違いが明確になります。

C#
public Order GetOrder(int orderId)
{
throw new NotImplementedException();
}

public Task<Order> GetOrderAsync(int orderId)
{
throw new NotImplementedException();
}

asyncキーワードを付けているかだけではなく、呼び出し側が待機する非同期処理であることを名前から判断できるようにするのが目的です。

イベントハンドラーなど、既存フレームワークの命名パターンがある場合は、その形式を優先することがあります。

4-3. プロパティ名の付け方

プロパティ名にはPascalCaseを使用し、値や状態を表す名詞または形容詞句を使います。

C#
public string CustomerName { get; set; } = string.Empty;

public decimal TotalPrice { get; private set; }

public DateTime CreatedAt { get; init; }

メソッドのような動詞句は避けます。

C#
// プロパティとしては不自然
public string GetCustomerName { get; set; } = string.Empty;

// 推奨
public string CustomerName { get; set; } = string.Empty;

コレクションを返す場合は、複数形を使用すると分かりやすくなります。

C#
public IReadOnlyList<Order> Orders { get; init; } = [];

4-4. イベント名の付け方

イベント名にはPascalCaseを使用し、何が発生したのかを表す名前にします。

C#
public event EventHandler? OrderCompleted;
public event EventHandler? CustomerCreated;
public event EventHandler? PaymentFailed;

処理の完了後に発生するイベントには、過去形を使うと状態が分かりやすくなります。

C#
OrderCreated
PaymentCompleted
FileDeleted

処理の前に発生し、キャンセルなどを受け付けるイベントでは、進行中を表す名前を使うことがあります。

C#
OrderCreating
FileDeleting
WindowClosing

イベント引数のクラスには、一般的にEventArgsサフィックスを付けます。

C#
public sealed class OrderCompletedEventArgs : EventArgs
{
public required int OrderId { get; init; }
}

4-5. boolを返すメソッド・プロパティの命名例

bool型の名前は、trueが何を意味するのか分かるようにします。

プロパティでは、IsHasCanなどを使うと状態を表現しやすくなります。

C#
public bool IsActive { get; init; }
public bool HasPermission { get; init; }
public bool CanCancel { get; init; }

メソッドでは、判定内容に応じて動詞を選びます。

C#
public bool ContainsItem(int itemId)
{
return true;
}

public bool ExistsCustomer(int customerId)
{
return true;
}

public bool CanProcess(Order order)
{
return true;
}

不自然な名前や意味が曖昧な名前は避けます。

C#
// 何がtrueなのか分かりにくい
public bool Check()
{
return true;
}

// 判定内容が分かる
public bool IsValidOrder(Order order)
{
return true;
}

5. C#の変数・フィールド・定数の命名規則

5-1. ローカル変数名の付け方

ローカル変数にはcamelCaseを使用します。

C#
string customerName = "Sato";
decimal totalPrice = 1200m;
DateTime createdAt = DateTime.Now;

型名をそのまま変数名にするのではなく、コード内での役割を表現します。

C#
// 型しか分からない
DateTime dateTime;

// 役割が分かる
DateTime orderDeadline;

ただし、型から役割が十分に明確な場合は、型名に近い変数名でも問題ありません。

C#
Customer customer;
Order order;
CancellationToken cancellationToken;

5-2. 引数名の付け方

メソッドの引数にはcamelCaseを使用します。

C#
public void CreateOrder(
int customerId,
IReadOnlyList<OrderItem> orderItems,
DateTime requestedDeliveryDate)
{
}

引数名は、呼び出し側でも読みやすい名前にします。

C#
CreateOrder(
customerId: 100,
orderItems: items,
requestedDeliveryDate: deliveryDate);

valuedataだけでは意味が不足する場合があります。

C#
// 曖昧
public void Update(string value)
{
}

// 具体的
public void UpdateCustomerName(string customerName)
{
}

5-3. フィールド名の付け方

privateフィールドには、_camelCaseを使う形式が一般的です。

C#
public class CustomerService
{
private readonly ICustomerRepository _customerRepository;
private int _retryCount;
}

フィールドの目的や保持する値が分かる名前にします。

C#
// 曖昧
private string _data;

// 具体的
private string _accessToken;

publicフィールドはカプセル化を損ねやすいため、必要性がなければプロパティを使用します。

C#
// publicフィールドよりも
public string CustomerName;

// プロパティを検討する
public string CustomerName { get; set; } = string.Empty;

5-4. privateフィールドにアンダースコアを使う場合

privateフィールドの先頭にアンダースコアを付けると、ローカル変数や引数と区別しやすくなります。

C#
public class UserService
{
private readonly IUserRepository _userRepository;

public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
}

アンダースコアを使わない規則の場合は、thisで区別できます。

C#
public class UserService
{
private readonly IUserRepository userRepository;

public UserService(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
}

どちらも文法上は正しいため、チーム内で統一されていることが重要です。

Microsoftの現在のC#ドキュメントでは、privateインスタンスフィールドに_、private staticフィールドにs_、スレッド静的フィールドにt_を使うスタイルが紹介されています。ただし、s_などはフレームワーク設計ガイドラインそのものではなく、プロジェクト側で設定できるスタイルです。Microsoft Learn+1

5-5. 定数(const)と読み取り専用フィールド(readonly)の命名

C#の一般的な命名規則では、定数にPascalCaseを使用します。

C#
public const int MaxRetryCount = 3;
private const string DefaultCountryCode = "JP";

ほかの言語でよく使われる、すべて大文字の形式を採用するプロジェクトもあります。

C#
private const int MAX_RETRY_COUNT = 3;

しかし、MicrosoftのC#命名ガイドでは定数もPascalCaseです。新規プロジェクトでは、特別な理由がなければ次の形式が自然です。Microsoft Learn+1

C#
private const int MaxRetryCount = 3;

privateのreadonlyフィールドは、通常のprivateフィールドと同じ形式にします。

C#
private readonly TimeSpan _defaultTimeout;
private readonly IOrderRepository _orderRepository;

public static readonlyフィールドはPascalCaseにします。

C#
public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);

5-6. 一時変数・ループ変数の命名例

狭い範囲の単純なループでは、ijを使用できます。

C#
for (int i = 0; i < customers.Count; i++)
{
Console.WriteLine(customers[i].Name);
}

ループが複雑な場合は、役割を表す名前にします。

C#
for (int customerIndex = 0; customerIndex < customers.Count; customerIndex++)
{
Customer customer = customers[customerIndex];
}

foreachでは要素の単数形を使用すると自然です。

C#
foreach (Order order in orders)
{
ProcessOrder(order);
}

一時変数でも、数行を超えて使う場合は具体的な名前を付けます。

C#
// 曖昧
var tmp = CalculateDiscount(order);

// 具体的
decimal discountAmount = CalculateDiscount(order);

6. C#で読みやすい名前を付けるコツ

6-1. 意味が伝わる具体的な名前にする

名前から、何の値なのか、何をする処理なのかが分かるようにします。

C#
// 曖昧
int count;

// 具体的
int failedLoginCount;
C#
// 曖昧
void Execute();

// 具体的
void SendPasswordResetEmail();

同じ型の値が複数登場する場合は、特に役割を明確にします。

C#
DateTime orderDate;
DateTime paymentDate;
DateTime deliveryDate;

6-2. 短すぎる名前・長すぎる名前を避ける

短すぎる名前は意味が不足します。

C#
var x = GetCustomer();
var d = DateTime.Now;

一方、長すぎる名前はコードの流れを妨げます。

C#
var customerWhoHasCompletedEmailAddressVerification =
GetVerifiedCustomer();

必要な情報だけを残します。

C#
var verifiedCustomer = GetVerifiedCustomer();

名前だけですべてを説明しようとせず、型、クラス、メソッド、スコープから読み取れる情報を活用します。

6-3. 省略語・略称を使うときの注意点

省略語は、チーム全員が同じ意味で理解できる場合だけ使用します。

C#
// 一般的に理解されやすい
customerId
requestUrl
httpClient

独自の省略語は避けます。

C#
// 意味を推測しにくい
custInf
ordDtl
payRslt

次のように省略せずに書くほうが明確です。

C#
customerInformation
orderDetails
paymentResult

同じ略語について、IdIDidなどの表記が混在しないようにします。

6-4. 動詞・名詞を使い分ける

クラスやプロパティには名詞、メソッドには動詞を使うのが基本です。

C#
// クラス:名詞
public class OrderCalculator
{
// プロパティ:名詞
public decimal TaxRate { get; init; }

// メソッド:動詞
public decimal CalculateTotal(Order order)
{
return 0;
}
}

判定メソッドでは、状態や条件を表す名前を使います。

C#
IsValid
CanCancel
ContainsProduct
HasPermission

6-5. 否定形や二重否定を避ける

否定形のbool名は、条件式を読みにくくすることがあります。

C#
bool isNotDisabled;

if (!isNotDisabled)
{
}

肯定形にすると読みやすくなります。

C#
bool isEnabled;

if (!isEnabled)
{
}

特に、否定演算子と否定形の名前が組み合わさる二重否定は避けます。

C#
// 読みにくい
if (!isNotAvailable)
{
}

// 読みやすい
if (isAvailable)
{
}

6-6. チーム開発で命名を統一するポイント

チーム開発では、個人の好みよりもプロジェクト全体の一貫性を優先します。

最低限、次の項目を決めておくとよいでしょう。

  • privateフィールドに_を付けるか

  • staticフィールドに専用プレフィックスを付けるか

  • 定数をPascalCaseにするか

  • IdIDのどちらを使うか

  • 非同期メソッドにAsyncを付けるか

  • DTOやAPIなどの略語をどう表記するか

  • テストメソッドをどの形式で命名するか

文章で規則を共有するだけでなく、.editorconfigやコード分析を使って自動化すると、レビュー時の指摘を減らせます。

7. C#の命名規則の具体例

7-1. クラス名の良い例・悪い例

C#
// 悪い例:役割が不明
public class Manager
{
}

// 良い例:注文を扱うサービス
public class OrderService
{
}
C#
// 悪い例:省略されすぎている
public class CustRepo
{
}

// 良い例
public class CustomerRepository
{
}
C#
// 悪い例:クラス名なのにcamelCase
public class paymentService
{
}

// 良い例
public class PaymentService
{
}

7-2. メソッド名の良い例・悪い例

C#
// 悪い例:何を実行するのか不明
public void Do()
{
}

// 良い例
public void SendInvoice()
{
}
C#
// 悪い例:処理内容が広すぎる
public void ProcessData()
{
}

// 良い例
public void ImportCustomerCsv()
{
}
C#
// 悪い例:戻り値の意味が分からない
public decimal GetValue()
{
return 0;
}

// 良い例
public decimal CalculateShippingFee()
{
return 0;
}

7-3. 変数名の良い例・悪い例

C#
// 悪い例
var d = DateTime.Now;
var n = customer.Name;
var x = order.TotalPrice;

// 良い例
var currentDateTime = DateTime.Now;
var customerName = customer.Name;
var totalPrice = order.TotalPrice;

ただし、スコープが極めて狭く意味が明白な場合は、過度に長い名前にする必要はありません。

C#
foreach (Customer customer in customers)
{
SendEmail(customer);
}

7-4. bool型の名前の良い例・悪い例

C#
// 悪い例
bool flag;
bool check;
bool status;

// 良い例
bool isActive;
bool hasPermission;
bool canDelete;

メソッドの場合も、判定内容を明示します。

C#
// 悪い例
bool Check(Order order);

// 良い例
bool IsValidOrder(Order order);
bool CanCancelOrder(Order order);

7-5. リファクタリング前後で見る命名改善例

リファクタリング前のコードです。

C#
public decimal Calc(List<Item> list, decimal r)
{
decimal v = 0;

foreach (var x in list)
{
v += x.Price * x.Count;
}

return v - v * r;
}

処理自体は短いものの、Calclistrvxが何を表しているのか分かりにくくなっています。

命名を改善すると、次のようになります。

C#
public decimal CalculateDiscountedTotal(
IReadOnlyList<OrderItem> orderItems,
decimal discountRate)
{
decimal subtotal = 0;

foreach (OrderItem orderItem in orderItems)
{
subtotal += orderItem.UnitPrice * orderItem.Quantity;
}

decimal discountAmount = subtotal * discountRate;
return subtotal - discountAmount;
}

コメントを追加しなくても、処理内容を追いやすくなりました。良い名前は、コードそのものを説明として機能させます。

8. C#の命名でよくある間違い

8-1. JavaやJavaScriptの命名規則と混同する

JavaやJavaScriptでは、メソッド名にcamelCaseを使うことが一般的です。

JavaScript
function calculateTotalPrice() {
}

C#では、メソッド名にPascalCaseを使うのが一般的です。

C#
public decimal CalculateTotalPrice()
{
return 0;
}

複数の言語を扱う場合は、現在編集している言語の規則に切り替える必要があります。

8-2. ハンガリアン記法を使ってしまう

ハンガリアン記法とは、名前に型情報を含める方法です。

C#
string strCustomerName;
int intCustomerCount;
bool bIsActive;

C#ではIDEから型情報を確認でき、型を変更すると名前との不一致も発生するため、通常は使用しません。

C#
string customerName;
int customerCount;
bool isActive;

型ではなく、値の意味や役割を名前に含めましょう。

8-3. 型名と変数名が似すぎて読みにくい

C#では、型名とそのインスタンスの変数名を次のようにすることがあります。

C#
Customer customer = new Customer();

これは自然な命名です。しかし、同じスコープで大文字と小文字だけが異なる名前を増やすと、読みづらくなります。

C#
Customer customer;
Customer Customer;
Customer CUSTOMER;

役割が異なる場合は、その違いを名前に含めます。

C#
Customer currentCustomer;
Customer selectedCustomer;
Customer billingCustomer;

8-4. 略語を多用して意味が伝わらない

次のコードは、作成者以外には意味を推測しにくくなっています。

C#
var usrInf = GetUsrInf();
var ordDts = GetOrdDts();
var pmtSt = GetPmtSt();

省略を減らすと理解しやすくなります。

C#
var userInformation = GetUserInformation();
var orderDetails = GetOrderDetails();
var paymentStatus = GetPaymentStatus();

文字数を減らすことよりも、読み手が意味を理解する時間を減らすことを優先しましょう。

8-5. 日本語ローマ字の変数名を使ってしまう

日本語をローマ字にした名前は、日本語話者には理解できても、単語の区切りや意味が曖昧になりやすい傾向があります。

C#
string kokyakuMei;
decimal uriageGokei;
DateTime shiharaiKigen;

可能であれば、一般的な英単語を使用します。

C#
string customerName;
decimal totalSales;
DateTime paymentDeadline;

ただし、業務固有の概念を無理に一般英語へ置き換えると、かえって意味が変わることがあります。業界用語の対訳表を用意し、チーム内で同じ英訳を使うことが重要です。

9. 命名規則を自動でチェック・統一する方法

9-1. Visual Studioのコード分析を使う

Visual Studioと.NETのコード分析機能を使用すると、命名規則やコードスタイルに関する問題をIDE上で確認できます。

ルール違反は、設定に応じて次のような重大度で表示できます。

  • 提案

  • 警告

  • エラー

Visual Studioのコードスタイル設定から.editorconfigを生成することもできます。コード分析を有効にすると、ローカル環境だけでなく、ビルドやCIでも規則違反を検出しやすくなります。Microsoft Learn+2Microsoft Learn+2

9-2. EditorConfigで命名ルールを設定する

.editorconfigを使用すると、プロジェクト単位で命名規則を定義できます。

たとえば、公開メンバーをPascalCaseにするルールは、次のように設定できます。

INI
root = true

[*.cs]

dotnet_naming_rule.public_members_should_be_pascal_case.symbols = public_members
dotnet_naming_rule.public_members_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.public_members_should_be_pascal_case.severity = warning

dotnet_naming_symbols.public_members.applicable_kinds = property, method, event, field
dotnet_naming_symbols.public_members.applicable_accessibilities = public, protected, protected_internal

dotnet_naming_style.pascal_case.capitalization = pascal_case

privateフィールドにアンダースコアを要求する例は次のとおりです。

INI
dotnet_naming_rule.private_fields_should_have_underscore.symbols = private_fields
dotnet_naming_rule.private_fields_should_have_underscore.style = underscore_camel_case
dotnet_naming_rule.private_fields_should_have_underscore.severity = warning

dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private

dotnet_naming_style.underscore_camel_case.required_prefix = _
dotnet_naming_style.underscore_camel_case.capitalization = camel_case

.NETの命名ルールは、主に次の3要素で構成されます。

  1. どのシンボルを対象にするか

  2. どの命名スタイルを適用するか

  3. 違反時の重大度をどうするか

.editorconfigはリポジトリに含められるため、開発者ごとのIDE設定に依存せず、プロジェクトのルールを共有できます。Microsoft Learn+1

9-3. 静的解析ツールで命名ミスを防ぐ

.NET SDKやVisual Studioで利用できるRoslynアナライザーを使うと、コードを実行せずに命名や品質上の問題を検出できます。

プロジェクトによっては、追加のアナライザーパッケージを導入し、次のような項目を検査します。

  • 命名規則

  • API設計

  • null安全性

  • 不要なコード

  • パフォーマンス上の問題

  • セキュリティ上の問題

重要なのは、ツールを導入するだけではなく、警告を放置しない運用を決めることです。

新規コードでは警告をエラーとして扱い、既存コードは段階的に改善する方法もあります。

9-4. チーム開発で命名ルールを共有する方法

命名規則は、次の3段階で共有すると効果的です。

まず、READMEや開発ガイドに、人が理解するためのルールを書きます。

・クラス、メソッド、プロパティはPascalCase
・引数とローカル変数はcamelCase
・privateフィールドは_camelCase
・非同期メソッドにはAsyncを付ける
・定数はPascalCase

次に、機械的に判定できる規則を.editorconfigへ記述します。

最後に、CIでビルドやコード分析を実行し、ルール違反を検出します。

この3つを組み合わせることで、「ルールはあるが誰も守っていない」という状態を防ぎやすくなります。

10. C#命名規則に関するよくある質問

10-1. privateフィールドには必ずアンダースコアを付けるべき?

必須ではありません。アンダースコアを付けなくても、C#の文法上は問題ありません。

C#
private readonly IUserRepository userRepository;

ただし、アンダースコアを付けると引数やローカル変数と区別しやすくなります。

C#
private readonly IUserRepository _userRepository;

public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}

新規プロジェクトでは_camelCaseを採用しやすい一方、既存プロジェクトで別の規則が統一されているなら、その規則を優先しましょう。

10-2. 定数はすべて大文字にするべき?

C#では、定数をすべて大文字にする必要はありません。

MicrosoftのC#命名ガイドでは、定数にPascalCaseを使用します。

C#
private const int MaxRetryCount = 3;

次の形式も他言語では一般的ですが、C#の標準的な表記とは異なります。

C#
private const int MAX_RETRY_COUNT = 3;

既存プロジェクトに明確な規則がない場合は、PascalCaseを選ぶと.NETのAPIや公式コードの雰囲気に合わせやすくなります。

10-3. インターフェイス名の先頭にはIを付けるべき?

通常は付けます。

C#
public interface IOrderRepository
{
}

先頭のIによって、利用者がインターフェイスであることをすぐに判断できます。.NETの一般的な命名規則とも一致します。

独自の理由で付けない設計も文法上は可能ですが、C#開発者の予想と異なるため、特別な事情がない限りIを付けるのが無難です。

10-4. メソッド名はどのように考えればよい?

最初に「このメソッドは何をするのか」を動詞で表現します。

たとえば、注文を保存するなら次の名前が候補になります。

C#
SaveOrder
CreateOrder
RegisterOrder

ただし、それぞれ意味が異なります。

  • SaveOrder:状態を保存する

  • CreateOrder:新しい注文を作成する

  • RegisterOrder:システムへ登録する

処理の実態に最も近い動詞を選びましょう。

名前が決まらない場合は、メソッドが複数の処理を担当していないか確認します。

C#
public void ValidateSaveAndSendOrder()
{
}

このような名前になる場合は、処理を分割できる可能性があります。

C#
ValidateOrder();
SaveOrder();
SendOrderConfirmation();

10-5. 既存プロジェクトの命名規則がバラバラな場合はどうする?

最初に、今後採用する基準を決めます。その後、.editorconfigやコード分析を導入し、新しく追加・変更するコードから統一していきます。

既存コードを一度にすべて変更すると、次の問題が起こりやすくなります。

  • 差分が大きくなりレビューしにくい

  • マージ競合が増える

  • 公開APIの変更が利用者へ影響する

  • リフレクションやシリアライズに影響する可能性がある

  • 本来の機能修正と命名変更が混ざる

そのため、次の順序で進めると安全です。

  1. 命名規則を文書化する

  2. .editorconfigへ設定する

  3. 新規コードから適用する

  4. 変更頻度の高い箇所を優先して直す

  5. 大規模な名称変更は専用のプルリクエストに分ける

  6. 公開APIや外部連携への影響を確認する

命名変更には、文字列の置換ではなく、IDEの「名前の変更」リファクタリング機能を利用しましょう。

まとめ

C#の命名では、次のルールを基本として覚えておくとよいでしょう。

  • クラス、構造体、列挙型はPascalCase

  • インターフェイスはI+PascalCase

  • メソッド、プロパティ、イベントはPascalCase

  • 引数とローカル変数はcamelCase

  • privateフィールドは_camelCase

  • 定数はPascalCase

  • 非同期メソッドにはAsyncを付ける

  • ジェネリック型パラメーターにはTまたはTEntityなどを使う

  • 名前には型ではなく役割や意味を表す

  • 略語、否定形、曖昧な単語を多用しない

命名規則は、コードを動かすためだけのルールではありません。クラスやメソッドの役割を明確にし、コードを読む時間や認識のずれを減らすための設計手段です。

公式のC#命名規則を基準にしながら、既存プロジェクトの慣習とチーム内の統一を優先し、.editorconfigやコード分析によって継続的にチェックできる環境を整えましょう。