LoginSignup
3
6

More than 5 years have passed since last update.

corefxリポジトリのコーディング規約(日本語訳)

Last updated at Posted at 2019-06-19

dotnet/corefxリポジトリ内のC# Coding Styleの日本語訳です。
コード部分および脚注は自分が書き加えたものです。

C++ファイル(*.cpp, *.h)

  • clang-format (version 3.6+)に準拠する。
    • マージ前にsrc/Native/format-code.shを実行して、コードの自動整形をすること。

コードファイル以外(*.xmlなど)

  • フォーマットの一貫性を優先する。
    • 修正の場合は、既存のフォーマットに準拠する。
    • 新規作成の場合は、すでに作成された同種ファイルのフォーマットに準拠する。
    • 準拠する既存のファイルがない場合は、広く受け入れられたスタイルであればOK。

C#ファイル(*.cs)

基本的にVisual Studioの初期設定に準ずる。

ブラケット{ }

  • Allman styleに準拠する。
  • 単一ステートメントのブラケットなし表記は許容するが、「インデントが適切である」「他のステートメントでネストされていない」場合のみ。(参考issue#381)
  • usingステートメントは例外で、他のusingにネストされていてもブラケットを省略可能。
Braces
// OK
public void Foo(int x, string y)
{
    // 単一ステートメントの場合は{ }がなくてもよい
    if (x < 0) throw new ArgumentException();

    // 2行に分ける場合も同様。ただしインデントは下げる
    if (y == null)
        throw new ArgumentNullException("Exception Message");

    // ネストされている場合は{ }必須
    if (x == 0)
    {
        if (y == "")
        {
            Console.WriteLine("String Empty");
        }
        Console.WriteLine("Int 0");
    }

    // 例外的に、usingはネストを深くしなくてよい
    using (var sr = new StreamReader())
    using (var sw = new StreamWriter())
    {
        // srとswのスコープはこのブロック内
    }
}

// NG(K&R style)
public void Bar(int x, string y) {

    // NGではないが、早期returnに{ }があるのは嫌われがち(issue#381)
    if (x < 0) { throw new ArgumentException(); }

    // NG(インデントを下げていない)
    if (y == null)
    throw new ArgumentNullException("Exception Message");

    // これはFooクラスと異なるコードパスとなる。
    // 以下のように解釈される。
    // =============================
    // if (x == 0)
    // {
    //     if (y == "")
    //     {
    //         Console.WriteLine("String Empty");
    //     }
    // }
    // Console.WriteLine("Int 0");
    // =============================
    // 上記のような勘違いを起こさないように、{ }を必須としている。
    if (x == 0)
        if (y == "")
            Console.WriteLine("String Empty");
        Console.WriteLine("Int 0");
}

インデント

  • 半角スペース4つ。(タブ文字は使わない)

フィールド

  • internalprivateフィールドの場合は_camelCaseのように命名する。
    • インスタンスフィールドは_をつける
    • staticフィールドはs_をつける
    • スレッド内でstaticなフィールドにはt_をつける
  • 可能ならばreadonlyをつける
  • staticreadonlyが重複する場合は、static readonlyの語順にする。
  • publicフィールドは多用しない。 使用する場合はPascalCaseのように命名する。
Fields
using System.Threading;

public class Foo
{
    private int _count;
    private static readonly string s_foo;
    [ThreadStatic]
    private static string t_bar;
    public string PublicField;
}

this参照

  • 必要でない限りは、this.表記を使わない。
This
public class Foo
{
    // フィールドの命名規約に違反していますが、例ということでご容赦を……。
    private readonly int x;
    private readonly int y;

    public Foo(int x)
    {
        // thisを付けないと引数のxとみなされるため、必須
        this.x = x;
        // NG yでアクセス可能
        this.y = 20;
    }
}

アクセシビリティ

  • 省略可能な場合であっても、privateなどのアクセシビリティは明示する。
  • アクセシビリティは先頭に書く。
Visiblity
internal class Foo  // OK
{
    private string _text;  // OK
}

public abstract class Bar  // OK
{
}

class Foo  // NG(明示的にinternalを書く)
{
    string _text;  // NG(明示的にprivateを書く)
}

abstract public class Bar  // NG(public abstractの順)
{
}

名前空間

  • 名前空間のインポート(using)は、ファイルの先頭かつ、namespaceブロックの外で行う。
  • System.*以外の名前空間は、アルファベット順にソートする。
  • System.*のインポート句は、先頭に持ってくる。
Namespace
using System;
using System.Text;
using ACorp.Library;
using BCorp.Library;
using BCorp.Library.IO;

namespace ACorp.Product
{
}

空白行

  • 空白行は1行まで。2行以上の空白行は認めない。

スペース

  • 行末のスペースなど、不要な空白は削除する。
    • IDEで明示的にスペースが見える設定にしておく。(Visual StudioではCtrl+E, S)
// NG 見た目ではわかり辛いが、下の行末にスペースが3個ある
if (index == 0)   
{
}

既存コード

  • 既存のコードファイルに、この規約に沿わないものがあった場合は、そのファイル内では既存の表記に従う。1

var

  • 右辺から型が明らかな場合のみ使用する。
Var
var stream = new FileStream();  // OK
var stream = OpenStandardInput();  // NG 戻り値の型を知らなければならない

組み込み型

  • BCLの型名(Int32など)ではなく、キーワード(int)を使用する。(参考issue#391)
    • int.Parseなど、メソッドを呼び出す際も同様。

定数(const)

  • ローカル定数とフィールド定数は、PascalCaseで命名する。
    • ネイティブコード呼び出し等で定数名と値を合わせる必要がある場合には、この限りではない。

nameof

  • 可能な限り、"Foo"ではなくnameof(Foo)演算子を利用する。
NameOf
public void Method(int index)
{
    // nameof演算子はコンパイル時に定数に変換される。
    // つまり、下記if文は同じ意味。
    // ただしnameof演算子を利用することで、IDE上での参照が追えるようになる。
    // (例えば引数indexをリネームした場合、前者は変更が追えるが後者は追えない)
    if (x < 0) throw new ArgumentException(nameof(index));
    if (x < 0) throw new ArgumentException("index");
}

フィールド宣言

  • フィールドは、型宣言の先頭に定義する。

非ASCII文字

  • 非ASCII文字は、Unicodeエスケープリテラル(\uXXXX)を用いて表記する。
    • 非ASCII文字に非対応のエディタで問題が起きないようにするため。

gotoラベル

  • goto用のラベルを書く際には、インデントを1段階上げる。
public void Method(int x)
{
    if (x < 0) goto Negative;
    DoSomething(x);
Negative:  // インデントを1段階上げる
    DoFinally();
}

ツール類

EditorConfig

  • corefxリポジトリのルートにある.editorconfigファイルで、上記規約をルール化している。
    • EditorConfigに対応しているエディタならば、上記の規約に従うよう自動整形される。2

.NET Codeformatter Tool

  • 実行時に、自動で上記の規約に沿うようファイルを整形するツール。

メモ


  1. 例えばシリアライズ可能なクラスの場合、privateなフィールドであっても、名称の変更は破壊的変更になり得る。こうした「何らかの理由があって変更できない」コードが変更されてしまうのを防ぐためのルールだと思われる 

  2. .NET拡張部分(フィールドの宣言など)は、Visual Studioのみの対応? 

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6