2011-01-21 3 views
1

私は理論を知っています、彼らは素晴らしいです、フレームワークに含まれているものは多くのものを簡素化し、彼らはさらにパフォーマンスを得ることができます。
このトピックに関する多くの回答がありますが、私には実用的価値が低く、フレームワークにすでに存在している例があります。

問題は、ジェネリックを使用する独自のクラスを作成することに決めましたか?
.netでのジェネリックの実用的な使用(フレームワークのもの以外)

+0

てきたオブジェクト指向についての本を読みました。 – Jaster

+0

は、パターンについての章をスキップしているようですが、最も簡単な例として工場を試してみてください。 – Jaster

答えて

2

さまざまな種類のオブジェクトに同じアルゴリズム/同じロジックを適用する必要があるたびに、ジェネリックを使用しています。 - 私は与えることができる(潜在的に... SO答える迅速のためにあまりにも関係している)、あまりにも多くの例

public interface IRepository<T> where T : class, IEntity 
{ 
    IQueryable<T> GetQuery(); 
    void Update(T entity); 
    void Insert(T entity); 
    void Delete(int id); 
} 

public interface IEntity 
{ 
    int Id { get; set; } 
} 
2

クラスがまだ定義されていない型の操作のセットを実行するときはいつでもジェネリックを使用します。

たとえば、数学演算のセットを実装するとしますが、クラスのユーザーが実際の数値タイプ(intshort、...)を決定できるとします。タイプを指定しない(汎用化することで)、汎用クラスをより広く使用することができます。

また、関連する利点は、ジェネリッククラスのために生成されたコードが実際にはより具体的であることです。キャスト操作が少なく、潜在的にランタイムテストが少なくなります。 .NETフレームワークの汎用コンテナは良い例です。

+0

それは良い引数ではなく、実際の実用的な例ではありますが、まだ有効です –

+0

非常に実用的!私は、ジェネリックスを使ってポイントクラスとベクトルクラスを実装し、そのクラスに対して幾何学演算をコード処理しました。実行時間は、ストレージタイプ(8ビット、16ビット、浮動小数点)に大きく依存し、使用するタイプはアプリケーションによって異なります。ジェネリックを使用することで、特定のアプリケーションに最適なコードを必ず使用することができます。 –

+0

今実際の実用的なもの、ありがとう –

1

うわー:

例は、一般的なリポジトリです。

多くの場所でジェネリックを使用します(特に、多くのシナリオで共通のパターンをまとめる)。しかし、私がそれらを置いた最も有益な使い方の1つは、オペランドの型に応じて変化するリフレクションベースのコードや他の動的コードを高速化し、同時に隠すことです。

たとえば、私の実際の例があまりにも複雑で抽象的な抽象的なものであるため、バックグラウンドのない抽象的なものですが、オブジェクトからデータ値をほとんど排他的に取り出すために文字列を使用するコンポーネントがあります。もちろん、それが1回か2回して問題ではない場合は、リフレクションを維持してください。しかし、そうしたら多くの場合、値をより迅速に取得できる動的なデリゲートをコンパイルすることができます。だから、

public static class NamedValueAccessor<T> 
{ 
    private Dictionary<string, Func<T, object>> _accessors; 
    private Dictionary<string, Action<T, object>> _writers; 

    public object GetValue(T instance, string name) { } 
    public void SetValue(T instance, string name, object newValue) { } 
} 

GetValueSetValuePropertyInfoCanReadCanWrite値をチェック、そのプロパティのタイプT上に反映することができます。すべてが正常であると確認されると、System.Linq.Expressionsを使用して読み込み/書き込みデリゲートを動的に構築し(すべてのリフレクション情報が利用可能なので簡単に)、辞書にキャッシュします。

最初の草稿を忘れてしまった - SetValue代理人は、ILを手作業で書いていない限り、.Net 4.0の式でしかコンパイルできないことに注意してください。それは何の制約がないため、すべてのタイプに適用することができ、

public static GetPropertyValue<T>(this T instance, string name) 
{ 
    return NamedValueAccessor<T>.GetValue(instance, name); 
} 

を:あなたは、おそらく拡張メソッド、他のジェネリックでこのクラスを使用することができますベースとしてこれにより

object - あなたが持っているものがすべてある場合は、GetType()メソッドを使用してランタイムタイプを取得することもできます。typeof(NamedValueAccessor).MakeGenericType(o.GetType()).GetMethod(...).Invoke(...)を実行します。しかし、同じパターンに従えば、この場合は、入力タイプの正しいNamedValueAccessor<T>.GetValueメソッドで焼かれた各Typeのデリゲートの動的キャッシュを構築する方がよいでしょう。

UPDATE

だから、ジェネリックは、この例では、私たちのために何をしたかを説明します

1)型に基づいたプロパティキャッシュは、コンパイラによって解決されるジェネリック型パラメータが既知である場合コンパイル時に(すなわちNamedValueAccessor<MyType>.GetValue("Foo"))、ジェネリックの特定のインスタンスにコンパイルされます。実行時に残されているのは、辞書の代理人を検索して実行することだけです。

2)別のタイプのキャッシュは)

3離れて保持されるキャッシュがサポートされるすべてのプロパティを取得するために型の上に、単純な反射と静的クラスの静的コンストラクタでプライミングされたことができ、プリ - すべてのデリゲートをコンパイルします。もちろん、実行時エラーをスローすることができないようにこのコードに注意する必要があります - 誰もTypeInitializationExceptionを好きではありません。これを行うと、マルチスレッド環境についても気にする必要はありません。キャッシュは不変です。

オンポイント3 - 型がIDynamicObjectの場合、もちろんこの戦略は失敗しますが、インスタンスの動的インターフェイスに委譲できます。実際に

ENDのUPDATE

、この私の使用は、単に、プロパティのセッターとゲッターをラップよりも複雑なものを行うことです(ComponentModel名前空間内のコードは、おそらくこのために優れている - のようにMvcがそれを活用する方法)、これらの種類のソリューションを適切に織り込むことで、エンドユーザー(私の場合はアプリケーションコーダー)に優れたパフォーマンスとアクセシビリティが提供されます。

この回答はあまりにも抽象的な投票になると思いますが、私たちは投票を得るための回答を提供していないので、とにかくそれを投げています。しかし、質問する人に知らせてください:)

+0

また、DLRの中心にあるこの種のものですが、キャッシュとロジックの背後には、私がここに示唆しているものよりもはるかに深いものがあります –

+0

このテクニックを使用して、コンパイラに反射の権利を使用する代わりにジェネリッククラス内のコードですか? –

+0

@クリスチャン - コメントで答えるつもりだった。いくつかの正当化を与える答えに余分な情報を追加することをお勧めします。 –

1

私はインターフェイスのカップルを実装するオブジェクトへの拡張メソッドを追加するためにジェネリック医薬品を使用するので、

public static MyExtension<T>(this T myobject) where T : ISomeInterface, ISomeOtherInterface 
{ 
    //Do some stuff on myObject 
} 
+0

ああ、F#の自動ジェネリックは人間的に可能です。 – Massif

関連する問題