web-dev-qa-db-ja.com

C#でのジェネリック型の適切な命名規則は何ですか?

この質問はスタックオーバーフローではなくここで行うことにしました。これは、主観的なものであるためです。

C#では、通常、非常に貧弱な名前のジェネリック型が表示されます。具体的には、「T」が一般的に使用されていますが、それ自体では意味のある名前ではありません。例えば:

class Fruit<T>
{
    T fruit;
}

これは典型的なアプローチですが、誰かこれを勧めませんか?もしそうなら、ジェネリック関数とクラスのC#のコンテキストでジェネリック型に適した命名規則は何でしょうか?

前の例では、ジェネリック型Tは常にAppleOrangeなどの果物のタイプである必要があると仮定します。タイプTは、それが果物のタイプであることを明確にする必要があるため、おそらくより適切な名前はFruitTypeになるため、次のようになります。

class Fruit<FruitType>
{
    FruitType fruit;
}

これは、私が何を求めているのかを皆さんに知らせるためのものです。この問題の受け入れ可能な「経験則」は何ですか?

17
void.pointer

それは確かに主観的です...ish
一部の人々は、iがforループ変数に対して完全に有効であると考えるので、Tは総称クラスの型プレースホルダーに対して完全に有効であると考えます。

私は個人的にこのアプローチを支持しています。それは一般的な慣習であり、人々一般的にはあなたの意味を知っています。

タイプが意味のある場所では、意味のある名前を使用しますが、通常はTで始めます。最近、一般的な辞書クラスを開発しました(質問しません)。宣言は

public class Dictionary<TKey, TValue>

ただし、タプルのようにタイプが本質的に無意味なものについては、以下を完全に許容できると考えています。

public class Tuple<T1, T2, T3>
22
Binary Worrier

マイクロソフトには、ジェネリックスに関する公式ガイドラインがあります。 クラス、構造体、およびインターフェイスの名前 (引用 ここ 、および本の形式: フレームワーク設計ガイドライン ) 。

あなたの特定の質問に関してそれは言う:

1文字の名前が完全に一目瞭然で、説明的な名前が価値をもたらさない場合を除き、説明的な名前でジェネリック型パラメーターに名前を付けます。

IDictionary<TKey, TValue> 

は、このガイドラインに従うインターフェースの例です。

1文字の型パラメーターを持つ型の型パラメーター名として、文字Tを使用することを検討してください。

説明的な型パラメーター名の前に文字Tを付けます。

パラメーターの名前の型パラメーターに課された制約を示すことを検討してください。たとえば、ISessionに制約されたパラメータはTSessionと呼ばれる場合があります。

8
Matthieu

Tはかなり標準になっていますが、私はあなたが正しいと思います。それはおそらく古いC++時代と「タイプTの」という表現に由来しています。私はできる限り説明的にすることをお勧めしますが、それは主観的なものです。

多くの人がインターフェースにIを選択するように、Tをプレフィックスとして選択できます。したがって

class Juice<TFruit> where TFruit...

私の控えめな意見では良い名前でしょう。私はほとんどの場合、接頭辞よりも接頭辞の方を好みます。偶然それに遭遇したときに何が表示されているかがすぐにわかり、Intellisenseなどで検索するのが簡単だからです。タイプ(TextBoxなど)は常に知っている可能性が高いが、それを説明する名前について100%確信が持てない場合は、UI-Controlsにとっても良い習慣です。

そのマイナス面は、型自体がTで始まると見栄えが悪いことです。そのため、以下のように、特殊な場合にジェネリック型をサフィックスに付けるのは良いことだと思います。

class SomeAlgorithm<TypeT> where TypeT : Type

これは私の意見であり、非常に主観的なものであることに注意してください。しかし、私は接尾辞よりも接頭辞を好むというマイナーなポイントを持っていると思います。

7
Falcon

ジェネリックの要点は、機能を委任することです。ジェネリッククラスは1つの処理を行い、その引数は別の処理を行います。教科書の例は一般的なコレクションです。コレクションには「もの」が格納されていますが、これらが何であるかは関係ありません。したがって、総称名(sic!)には特定のロジックがあります。「T」という名前が網羅している「総称型の引数です」以外は何も記述されていないため、説明的にしたくありません。規約を考慮してください)。説明的であることは良いことですが、過度に説明的であることはそこにない制限を示唆しています。

ただし、ジェネリッククラスまたはメソッドに複数の型パラメーターがある場合があります。この時点で、よりわかりやすい名前を付けて、役割が明確になるようにするのが理にかなっています。良い例は、キーと値の両方がジェネリックであるキーと値のコレクション型です。それらをTおよびS(またはQなど)と呼ぶと、たとえばKeyTypeValueType、またはTKeyTValと呼ぶよりも有用性が低くなります。

2
tdammers

答えは確かに主観的です。ただし、コードは自己文書化する必要があるため、質問としてのメリットはあります。

以下は、私が学んで従った規則です。

  • ジェネリック型パラメーターは、具象クラスと間違えられるべきではありません。これは一般に、インターフェースが一般にTで始まるように、後続の内容に関係なくIの序文を奨励します。

  • 通常、クラスまたはメソッドの単一のジェネリック型パラメーターには、Tというラベルを付ける必要があります。これは、C++テンプレートにさかのぼる、ほぼ普遍的に理解されている規則です。

  • 同じクラスまたはメソッド宣言の複数のジェネリック型パラメーターはすべてTで始まる必要がありますが、簡潔ですが理解できる手段によって区別されます。たとえば、TInおよびTOutは、強く型付けされたジェネリック入力を受け入れ、強く型付けされたジェネリック出力を生成するメソッドの一般的でよく理解されているGTPです。

  • .Netのタプルなどの包含クラスや、Func、Predicate、Actionなどのデリゲート型など、区別されているが注目に値しない複数の型には、T1、T2、T3などのラベルを付けることができます。 /または非常に具体的なタイプの制限)は、より説明的なものにする必要があります。

  • メソッドの単一のジェネリック型は、それを含むクラスのジェネリック型とは異なり、クラスまたはメソッドの複数の型に関する前のルールに従うことができますOR型が目立たない場合異なる場合とは異なり、UまたはVのように別の1文字を指定できます。これも、C++テンプレートにさかのぼる慣例です。

  • 何をするにしても、一貫性を保ちます。 2番目のクラスが最初のクラスにネストされて2番目のクラスでTが使用できないようにしない限り、1つのクラスTParamと次のTのGTPにラベルを付けないでください。

1
KeithS