Visual Studio で C# の命名規則をチェックする

# TOC
[__1. はじめに__](#はじめに)
[__2. 命名のスタイル__](#命名のスタイル)
[__3. Microsoft が推奨する命名規則__](#Microsoft-が推奨する命名規則)
[__4. Visual Studio で命名規則を設定する__](#Visual-Studio-で命名規則を設定する)


# はじめに
他の多くの言語と同様に、C#のコーディング規約ではクラスや関数、変数の命名規則が定められています。

https://learn.microsoft.com/ja-jp/dotnet/csharp/fundamentals/coding-style/coding-conventions

命名規則を定めることで、コードに統一性を持たせて可読性を向上させ、リーディングコストを削減できます。チーム開発には必須のルールであり、細則は会社やプロジェクト単位で定められていることが多いでしょう。
しかし日常的に複数の言語を使っていると、なかなか命名規則を覚えられません。そこでVisual Studioのオプションで命名規則をチェックできるよう設定します。

> Env
> - Visual Studio 2019
> - C#.NET



# 命名のスタイル
識別子の命名のスタイルとして、以下のようなものがよく使われます。


### キャメルケース
名前（複数の単語）を一語に繋げて表記する際に、各単語の先頭を大文字にするスタイルを __キャメルケース__ と呼びます。そのうち、先頭の単語のみ小文字で表記するものを __ローワーキャメルケース__ といい、単にキャメルケースといった場合はこちらを指すことが多いです。
```
"camel case" → camelCace
```

:::note warn
本記事では __キャメルケース = ローワーキャメルケース__ として記載します。
:::


### パスカルケース
キャメルケースのうち、最初の語も含めて各単語の最初を大文字で書くスタイルを __アッパーキャメルケース__ もしくは __パスカルケース__ と呼びます。C#.NETやVBAなどのMicrosoft製品の仕様としてよく採用されているスタイルです。
```
"pascal case" → PascalCace
```


### スネークケース
各単語をアンダースコアで繋ぐ（空白文字をアンダースコアに置き換える）スタイルを __スネークケース__ と呼びます。通常はすべて小文字で表記します。
```
"snake case" → snake_cace
```


### コンスタントケース
スネークケースのうち、すべて大文字で表記するスタイルを __アッパースネークケース__ あるいは __コンスタントケース__ と呼びます。定数や環境変数などの名前として用いられることが多いスタイルです。
```
"constant case" → CONSTANT_CASE
```


### ハンガリアン記法
上記のスタイルと組み合わせて、規則に則ったプレフィックスやサフィックスを付け、型やスコープに関する情報を付け加えるスタイルを __ハンガリアン記法__ と呼びます。型を修正すると識別子を全て修正しなくてはならないなど修正コストが高く、命名規則がしっかりしていればそもそも不要であるため、現在は推奨されていないスタイルです。
```:String型
"hungarian notatione" → strHungarianNotatione
```
```:Int型
"hungarian notatione" → intHungarianNotatione
```

# Microsoft が推奨する命名規則

### ハンガリアン記法を使用しない
古いコードではハンガリアン記法が使用されていることがありますが、前項で述べたように現在は推奨されていません。ただしC#では、プレフィックスを付けてスコープに関する情報を付け加える場合があります。


### 名前空間と型名を競合させない
名前空間とその名前空間にある型に同じ名前を使用したり、`Element`、`Node`、`Log`、`Message` などのジェネリック型の名前を使用してはいけません。


### 省略形または短縮形を識別子名の一部として使用しない
例として、UIDocumentを取得する関数は、`GetUIDoc` ではなく `GetUIDocument` を使用します。


### 簡潔さよりも読みやすさを優先する
例として、画面を縦方向にスクロールするプロパティ名は、`ScrollableX` ではなく `CanScrollHorizontally` を使用します。



# Visual Studio で命名規則をチェックする
Visual Studio には命名規則をチェックするオプションがあり、命名規則にあっていない箇所に線が引かれるように設定できます。

### 1. オプション画面を開く
メニューバーから「ツール」→「オプション」をクリックし、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/5de5e042-5780-cf07-78ab-537eb2c9a087.png)

「テキスト エディター」→「C#」→「コードスタイル」→「名前指定」 を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/d12f4bc6-925b-2987-0d9a-ebc99d7686b5.png)


### 2. スタイルを追加する
「名前付けスタイルを管理する」を選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/2b888195-b263-4342-6de9-b32f7e3fc610.png)

「＋」を選択してパスカルケースやキャメルケースなどのスタイルを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/1a0b8e99-09cd-10e2-1988-aada4bafc490.png)


### 3. 仕様を追加する
「仕様の管理」を選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/243b6304-07a2-0deb-0db3-5ed3834b6399.png)

「＋」を選択して仕様（シンボルの種類やアクセシビリティのフィルターのようなもの）を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/31df5323-ead1-42af-6255-6271e6e43184.png)


### 4. 各仕様のスタイルと重要度を設定する
手順3で設定した仕様に手順2で設定したスタイルを割り当てます。また、重要度を設定して命名規則違反の個所を報告させます。

|重要度の種類||
|---|:---|
|❌エラー|命名規則違反の個所に赤線が引かれます|
|⚠️ 警告|命名規則違反の個所に緑の線が引かれます|
|ℹ️提案事項|命名規則違反の個所の先頭に破線が引かれます（※分かりにくいです）|
|⚪リファクタリングのみ|線は引かれず、カーソルを合わせると電球マークが表示されます|


### 筆者の設定
- Interface の先頭は大文字の __「I」__
- Public なフィールドは __キャメルケース__
- private または internal のフィールドはキャメルケースで **「_」** プレフィックスを付ける
    - そのうちstaticなものは **「s_」** プレフィックスを付ける
- メソッド パラメーターは __キャメルケース__
- 上記以外は __パスカルケース__
- すべての重要度を __エラー__ に設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/62c1ce07-0d7f-133d-5256-d98352d9478f.png)


### エラーの例
クラス名をキャメルケースにすると緑の線が引かれ、カーソルを合わせると修正が提案されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/5f103655-a0dd-c092-086c-1854cc64fb89.png)


# 設定を EditorConfig で出力する
※ 02.15追記

「テキスト エディター」→「C#」→「コードスタイル」→「全般」→「設定から .editorconfig ファイルを生成」を選択し、設定した命名規則を __.editorconfig ファイル__ として出力することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2059946/b0f0bf73-a8c8-36e4-f37a-ecafa061117f.png)

.editorconfig ファイルの詳細については以下のリンクを参照してください。

https://learn.microsoft.com/ja-jp/dotnet/fundamentals/code-analysis/code-style-rule-options?view=vs-2022#language-conventions

```config:.editconfig
# 上位ディレクトリから .editorconfig 設定を継承する場合は、以下の行を削除します
root = true

# C# ファイル
[*.cs]

#### コア EditorConfig オプション ####

# インデントと間隔
indent_size = 4
indent_style = space
tab_width = 4

# 改行設定
end_of_line = crlf
insert_final_newline = false

#### .NET コーディング規則 ####

# using の整理
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
file_header_template = unset

# this. と Me. の設定
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false

# 言語キーワードと BCL の種類の設定
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true

# かっこの設定
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity

# 修飾子設定
dotnet_style_require_accessibility_modifiers = for_non_interface_members

# 式レベルの設定
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true
dotnet_style_explicit_tuple_names = true
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true
dotnet_style_object_initializer = true
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true
dotnet_style_prefer_compound_assignment = true
dotnet_style_prefer_conditional_expression_over_assignment = true
dotnet_style_prefer_conditional_expression_over_return = true
dotnet_style_prefer_inferred_anonymous_type_member_names = true
dotnet_style_prefer_inferred_tuple_names = true
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_simplified_boolean_expressions = true
dotnet_style_prefer_simplified_interpolation = true

# フィールド設定
dotnet_style_readonly_field = true

# パラメーターの設定
dotnet_code_quality_unused_parameters = all

# 抑制の設定
dotnet_remove_unnecessary_suppression_exclusions = none

# 改行設定
dotnet_style_allow_multiple_blank_lines_experimental = true
dotnet_style_allow_statement_immediately_after_block_experimental = true

#### C# コーディング規則 ####

# var を優先
csharp_style_var_elsewhere = false
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = false

# 式のようなメンバー
csharp_style_expression_bodied_accessors = true
csharp_style_expression_bodied_constructors = false
csharp_style_expression_bodied_indexers = true
csharp_style_expression_bodied_lambdas = true
csharp_style_expression_bodied_local_functions = false
csharp_style_expression_bodied_methods = false
csharp_style_expression_bodied_operators = false
csharp_style_expression_bodied_properties = true

# パターン マッチング設定
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true
csharp_style_prefer_switch_expression = true

# Null チェック設定
csharp_style_conditional_delegate_call = true

# 修飾子設定
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async

# コード ブロックの設定
csharp_prefer_braces = true
csharp_prefer_simple_using_statement = true

# 式レベルの設定
csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
csharp_style_pattern_local_over_anonymous_function = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_range_operator = true
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable

# 'using' ディレクティブの基本設定
csharp_using_directive_placement = outside_namespace

# 改行設定
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true

#### C# 書式ルール ####

# 改行設定
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true

# インデント設定
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true

# スペース設定
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false

# 折り返しの設定
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true

#### 命名スタイル ####

# 名前付けルール

dotnet_naming_rule.interface_should_be_begins_with_i.severity = error
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i

dotnet_naming_rule.publicフィールド_should_be_camel_case.severity = error
dotnet_naming_rule.publicフィールド_should_be_camel_case.symbols = publicフィールド
dotnet_naming_rule.publicフィールド_should_be_camel_case.style = camel_case

dotnet_naming_rule.staticフィールド_should_be_begin_with_s_.severity = error
dotnet_naming_rule.staticフィールド_should_be_begin_with_s_.symbols = staticフィールド
dotnet_naming_rule.staticフィールド_should_be_begin_with_s_.style = begin_with_s_

dotnet_naming_rule.フィールド_should_be_begin_with__.severity = error
dotnet_naming_rule.フィールド_should_be_begin_with__.symbols = フィールド
dotnet_naming_rule.フィールド_should_be_begin_with__.style = begin_with__

dotnet_naming_rule.ローカル変数_引数_should_be_camel_case.severity = error
dotnet_naming_rule.ローカル変数_引数_should_be_camel_case.symbols = ローカル変数_引数
dotnet_naming_rule.ローカル変数_引数_should_be_camel_case.style = camel_case

dotnet_naming_rule.all_should_be_pascal_case.severity = warning
dotnet_naming_rule.all_should_be_pascal_case.symbols = all
dotnet_naming_rule.all_should_be_pascal_case.style = pascal_case

# 記号の仕様

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers = 

dotnet_naming_symbols.フィールド.applicable_kinds = field
dotnet_naming_symbols.フィールド.applicable_accessibilities = *
dotnet_naming_symbols.フィールド.required_modifiers = 

dotnet_naming_symbols.staticフィールド.applicable_kinds = field
dotnet_naming_symbols.staticフィールド.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.staticフィールド.required_modifiers = static

dotnet_naming_symbols.publicフィールド.applicable_kinds = field
dotnet_naming_symbols.publicフィールド.applicable_accessibilities = public
dotnet_naming_symbols.publicフィールド.required_modifiers = 

dotnet_naming_symbols.all.applicable_kinds = *
dotnet_naming_symbols.all.applicable_accessibilities = *
dotnet_naming_symbols.all.required_modifiers = 

dotnet_naming_symbols.ローカル変数_引数.applicable_kinds = parameter, type_parameter, local
dotnet_naming_symbols.ローカル変数_引数.applicable_accessibilities = *
dotnet_naming_symbols.ローカル変数_引数.required_modifiers = 

# 命名スタイル

dotnet_naming_style.pascal_case.required_prefix = 
dotnet_naming_style.pascal_case.required_suffix = 
dotnet_naming_style.pascal_case.word_separator = 
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix = 
dotnet_naming_style.begins_with_i.word_separator = 
dotnet_naming_style.begins_with_i.capitalization = pascal_case

dotnet_naming_style.begin_with__.required_prefix = _
dotnet_naming_style.begin_with__.required_suffix = 
dotnet_naming_style.begin_with__.word_separator = 
dotnet_naming_style.begin_with__.capitalization = camel_case

dotnet_naming_style.camel_case.required_prefix = 
dotnet_naming_style.camel_case.required_suffix = 
dotnet_naming_style.camel_case.word_separator = 
dotnet_naming_style.camel_case.capitalization = camel_case

dotnet_naming_style.begin_with_s_.required_prefix = s_
dotnet_naming_style.begin_with_s_.required_suffix = 
dotnet_naming_style.begin_with_s_.word_separator = 
dotnet_naming_style.begin_with_s_.capitalization = camel_case
```