======================================================================== C# コーディング規則 (C# Coding Style Guide) ======================================================================== 1. 基本方針 (Basic Policy) ------------------------------------------------------------------------ Microsoft の C# コーディング規則および .NET ランタイム コーディングガイド ラインを基本とし,チーム内での一貫性を最優先とする. 本規則に明記されていない事項は Microsoft 公式ガイドラインに従う. ※ 書式・記述スタイルの基準は `GUIDE_01_ドキュメント作成ガイド.txt` を参照する. 2. フォーマット (Formatting) ------------------------------------------------------------------------ 2-1. インデント ・半角スペース4つを使用する.タブ文字は使用しない. ・継続行は,開き括弧に揃えるか,ハンギングインデント(スペース4つ追加)とする. ・例: // 開き括弧に揃える var result = SomeMethod(argOne, argTwo, argThree, argFour); // ハンギングインデント var result = SomeMethod( argOne, argTwo, argThree, argFour); 2-2. 波括弧 (Braces) ・開き波括弧「{」は,宣言と同じ行に記述する(K&R スタイル). ・例: namespace TIASshot { internal class MotorController { public void Start() { if (IsRunning) { ... } } } } ・単文の `if` / `for` 等でも,必ず波括弧を付ける. - NG: `if (isActive) return;` - OK: `if (isActive) { return; }` 2-3. 1行の最大文字数 ・120文字を目安とする.超える場合は適切な位置で改行する. 2-4. 空行 ・クラス定義の間: 2行空ける. ・メソッド定義の間: 1行空ける. ・メソッド内の論理的なまとまりの区切り: 1行空ける(使いすぎに注意). 2-5. 文字コード ・UTF-8(BOM なし)を使用する. 3. 命名規則 (Naming Conventions) ------------------------------------------------------------------------ 3-1. 一覧 ■ クラス・構造体・列挙型・デリゲート ・スタイル: PascalCase ・例: `CameraBase`,`MotorController`,`DeviceStatus` ■ インターフェース ・スタイル: 「I」プレフィックス + PascalCase ・例: `ICamera`,`IDeviceControl` ■ メソッド・イベント・プロパティ ・スタイル: PascalCase ・例: `Connect()`,`GetDataName()`,`IsCalibrating` ■ ローカル変数・引数 ・スタイル: camelCase ・例: `cameraList`,`saveFolder`,`numImages` ■ プライベートフィールド ・スタイル: アンダースコア + camelCase ・例: `_camera`,`_isLightOn`,`_calibrating` ■ 定数・static readonly フィールド(公開) ・スタイル: PascalCase ・例: `MaxSpeed`,`DefaultPort`,`AppName` ※ 既存コードの `UPPER_SNAKE_CASE`(例: `APP_NAME`)は互換性のため許容するが, 新規定義は `PascalCase` に統一する. ■ 非同期メソッド ・スタイル: PascalCase + `Async` サフィックス ・例: `ConnectAsync()`,`SaveImagesAsync()`,`LoadConfigAsync()` ■ 列挙型メンバー ・スタイル: PascalCase ・例: `DeviceStatus.Connected`,`CaptureMode.Single` 3-2. 命名の原則 ・意味のある名前を付け,略語は最小限にする. - NG: `d`,`tmp`,`val` - OK: `distance`,`temperature`,`motorValue` ・ループカウンタ等,スコープが極めて狭い場合のみ `i`,`j`,`x`,`y` を許容する. ・bool 型のプロパティ・変数は `Is`,`Has`,`Can` 等の接頭辞を付ける. - 例: `IsConnected`,`HasObstacle`,`CanCapture` 4. using ディレクティブの規則 (Using Directives) ------------------------------------------------------------------------ 4-1. 順序 以下の順序で記述し,グループ間に1行空ける. 1. System 名前空間(`System`,`System.Collections.Generic` 等) 2. サードパーティライブラリ(`OpenCvSharp`,`TIS.Imaging` 等) 3. プロジェクト内名前空間 ・例: using System; using System.Collections.Generic; using System.IO; using OpenCvSharp; using TIASshot.Camera; 4-2. スタイル ・不要な `using` は削除する. ・`using static` は,同一クラスのメンバーを多用する場合のみ許容する. 5. 型の使用規則 (Type Usage) ------------------------------------------------------------------------ 5-1. var の使用 ・右辺に型名が明示されている場合は `var` を使用する. - OK: `var list = new List();` - OK: `var controller = new MotorController();` ・右辺から型が読み取れない場合は明示的な型を使用する. - NG: `var result = GetResult();`(戻り値の型が不明確) - OK: `XmlNode result = doc.SelectSingleNode("//Config");` 5-2. null 許容参照型 (Nullable Reference Types) ・`null` との比較は `is null` / `is not null` を使用する. - NG: `if (value == null)` - OK: `if (value is null)` ・null 合体演算子(`??`,`??=`)や null 条件演算子(`?.`,`?[]`)を積極的に活用する. 6. コーディングルール (Coding Rules) ------------------------------------------------------------------------ 6-1. 文字列 ・文字列の組み立てには文字列補間(`$"..."`)を使用する. - NG: `"Speed: " + speed.ToString()` - OK: `$"Speed: {speed}"` ・定数文字列は `const string` または `static readonly string` で定義する. 6-2. 例外処理 ・裸の `catch (Exception)` は極力避け,具体的な例外クラスを指定する. - NG: `catch (Exception) { }` - OK: `catch (ArgumentException ex) { ... }` ・例外を握りつぶす場合(空の catch 節)は,必ず理由をコメントで明記する. 6-3. リソース管理 ・`IDisposable` を実装するオブジェクトは `using` 文で管理する. ・例: using (var reader = new StreamReader(csvFile)) { while (!reader.EndOfStream) { ... } } 6-4. マジックナンバーの禁止 ・意味のある数値や文字列は定数として定義する. - NG: `Thread.Sleep(500);` - OK: const int SensorIntervalMs = 500; Thread.Sleep(SensorIntervalMs); 6-5. readonly の使用 ・コンストラクタ以降に値が変わらないフィールドは `readonly` を付ける. - NG: `private float _updateRate;`(コンストラクタで1度だけ代入する場合) - OK: `private readonly float _updateRate;` ・`static readonly` はクラス定数(`const` にできない参照型など)に使用する. 6-6. プロパティ vs 公開フィールド ・`public` フィールドは原則定義しない.外部に公開する値はプロパティを使用する. - NG: `public string DeviceName;` - OK: `public string DeviceName { get; protected set; }` ・外部から読み取りのみ許可する場合は `get` のみ,または `{ get; private set; }` とする. 6-7. アクセス修飾子 ・アクセス修飾子は必ず明示する(省略しない). - NG: `class Config { ... }` - OK: `internal static class Config { ... }` 6-8. UI スレッド ・ワーカースレッドから UI 操作を行う場合は `InvokeRequired` を確認してから `Invoke` / `BeginInvoke` を使用する. ・例: public void ShowMessage(string msg) { if (InvokeRequired) { Invoke((MethodInvoker)delegate { ShowMessage(msg); }); return; } txtMessage.Text = msg; } 7. ファイル構成 (File Structure) ------------------------------------------------------------------------ 1つの C# ファイル内は,以下の順序で記述する. 1. using ディレクティブ 2. namespace 宣言 3. クラス定義(フィールド → プロパティ → コンストラクタ → メソッド) ・例: using System; using System.IO; namespace TIASshot { internal class MotorController { // フィールド private bool _isRunning = false; // プロパティ public bool IsRunning => _isRunning; // コンストラクタ public MotorController() { ... } // メソッド public void Start() { ... } } } 8. ツール設定 (Tooling) ------------------------------------------------------------------------ コードの品質を自動で維持するため,以下のツールの導入を推奨する. ■ フォーマッター ・`.editorconfig` に本規則の設定を記述し,チームで共有する(IDE 共通). ・Visual Studio: Ctrl+K, Ctrl+D でフォーマットを実行する. ・VSCode: C# Dev Kit 拡張機能を導入し,Shift+Alt+F でフォーマットを実行する. - 保存時自動フォーマット(`editor.formatOnSave: true`)の設定を推奨する. ■ リンター ・Roslyn Analyzers を使用する(Visual Studio・VSCode 共通で動作する). - `Microsoft.CodeAnalysis.NetAnalyzers` パッケージの導入を推奨する. ■ 型チェック ・Visual Studio・VSCode いずれの場合も,ビルドエラー・警告を全て解消してからコミットする. ・dotnet CLI: `dotnet build` でエラーがないことを確認する. ※ ツールの具体的な設定や導入手順は `ENV_` カテゴリのドキュメントに記載する.