13

(たとえば、多くのモッキング ライブラリで) type の引数の代わりにジェネリック型引数が使用されるメソッドをよく見かけますSystem.Type。具体的には、ジェネリック型がtypeof(T)操作でのみ使用されている場合 (つまり、型 T のインスタンスがメソッド内のどこでも使用されておらず、T が戻り値の型または他の引数のいずれにも使用されていない場合) について話しています。

たとえば、次の方法を検討してください。

public string GetTypeName(System.Type type) { return type.FullName; }

このメソッドには、一般的なバージョンが付随することがよくあります。

public string GetTypeName<T>() { return GetTypeName(typeof(T)); }

質問 それは悪い習慣ですか、それとも良い習慣ですか?
これはシンタックス シュガーですか、それとも他にもありますか?

これは、言語機能を悪用して、型の引数を受け入れるメソッドの呼び出しを省略していると思いますSystem.Type

これを匂いだと思いますか?これは避けるべきですか?または、これは実際には良い習慣です(入力を避けるためのショートカットとしてジェネリックメソッドを提供するためtypeof())。

私が考えることができるこのパターンを使用する際のいくつかの実際的な問題を次に示します。

  1. 非 System.Type 型の引数が追加された場合 - (引数の順序が意味的に重要な場合) メソッドを非ジェネリック バージョンに書き直す必要ある場合があります (そうでない場合、一部の引数はジェネリック型引数になり、一部は通常の引数になります)。
  2. 2 つのメソッドが必要です (コンパイル時に型がわからない場合は、ジェネリックと非ジェネリック)。その結果、ほとんど意味のない単体テストが追加されます。

一方、これは一般的な方法です (大多数は常に正しいですよね?) が、さらに重要なことに、ReSharper は、コンパイル時に既知の型 System.Type の単一の引数を必要とするコードで Extract Method リファクタリングを行うときに、その署名を好みます (そして私は彼らの勧告を信仰ではなく真剣に受け止めることを学びました)。

4

6 に答える 6

1

ジェネリックの理由であるデザインパターンの誤用(誤用はおそらく強いですが、正しい言葉が思い浮かびません)であるため、パターンを使用しませんstring GetName<T>() { return typeof(T).Name; }。つまり、ジェネリック型パラメーターはコンパイラー用にあり、タイプ固有のストレージ、パラメーター、スタック変数などを生成できるように、JITter (この質問への回答を参照)。

実行時に型引数を渡すための便利な方法として使用すると、匂いがします。必要な場合もありますがtypeof(T)、それらはまれであり、通常、単純なタイプ セーフの種類のものとは対照的に、ジェネリックで複雑なことを行う場合にのみ必要であることがわかりました。もし私がそれを見たら、私は間違いなく立ち止まって、なぜそこにあるのか自問します.

于 2013-10-16T17:21:30.597 に答える
0

Typeジェネリック メソッドは、指定された型を使用して他のジェネリックなものを参照できるため、 type のパラメーターを持つメソッドよりも利点があります。これは、次のシナリオで特に役立ちます。

public string GetTypeName<T>()
{ 
    return Cache<T>.TypeName;
}

private static class Cache<T>
{
    public static readonly TypeName = GetTypeName(typeof(T));
}

このキャッシュは簡単です。辞書をいじる必要はなく、自動的にスレッドセーフになります。

これは、実装がこの可能性を使用していない場合、2つの違いは表面的なものに過ぎないと言われています。

于 2013-10-16T14:10:36.463 に答える
0

すでに述べたように、それは個人的な好みの問題のように思えます。私の経験から、 Type 型の引数を受け取るほとんどのメソッドは、付随する拡張メソッドを使用して構文的に「甘く」することができます。

したがって、あなたの例の場合、2番目の方法を拡張します。このアプローチを使用すると、2 番目の懸念に対する解決策が得られます。不要な単体テストは必要ありません。ただし、最初のものは残ります。ただし、引数の追加にはリファクタリングが必要になるため、拡張メソッドのコンシューマーを変更して、元のメソッドの変更されたバージョンを使用する機会を提供します。

もちろん、あくまでも個人的な意見です。

于 2013-10-16T13:52:36.567 に答える