レビューは......私は自分自身貧しい言語能力の非常に恥ずかしいので、私を許してください...推定されているタイトルを見た後、私は、特に背中の先頭に句を書いた......
問題
一つの問題は、一昨日に遭遇したので、MSDNに尋ね作られたばかりのジェネリック医薬品については、次の質問を豊かに、。
こうした「EFがモデル初のジェネリックのサポートを追加することができます。」として、EFの最近の試みDDDしばしば奇妙なアイデア、これは、「引数を持つジェネリック型制約モードがあるかどうか」です。
具体的なアイデアは、私はジェネリックを使用するとき、私は型パラメータをインスタンス化する必要があることを発見し、非常に簡単です:
1 クラス MyClassの<T> 2 { 3 パブリックMyClass1() 4 { 5 本 .MyObject = 新しいT(); 6 } 7 8 T MyObjectに{ 得ます。セット; } 9 }
もちろん、上記のエラーになります。
Tのエラー内容を取得するには、レビューMSDNの下に新しい制約(新しい制約)、ではないジェネリック型パラメータの新しい制約の内容を。
だから、次の正しいコードは次のとおりです。
1 クラス MyClassの<T> 2 T:新しい() 3 { 4 パブリックMyClass1() 5 { 6 本 .MyObject = 新しいT(); 7 } 8 9 T MyObjectに{ 得ます。セット; } 10 }
その後、私はパラメータに基づいて、新しいオブジェクトを作成する必要があることを発見し、この方法は、最も適切な一般的なコンストラクタで実装されているので、私はこのコードを持っていると思ってい:
1 クラス MyClass1 <T> 2 T:新しい(文字列) 3 { 4つの公共 MyClassの(文字列要求) 5 { 6 本 .MyObject = 新しいT(要求)。 7 } 8 9 T MyObjectに{ 得ます。セット; } 10 }
残念ながら、この場合は非常に間違っているだろうし、その後見直しジェネリックリスト制約の道を、見つけるような制約のパラメータなしのコンストラクタを。
だから、僕は上記起こっ尋ねるMSDNにその質問求めて、「エレガントなソリューションを。」
2種類の一般的なソリューションと同じように、問題の答えが、また、私たちは見に回し、2は非常に不幸みました。
彼は加えました:
- James.Yingのリマインダだけでなく、コンストラクタから渡します
- Activator.CreateInstanceで、@Chooで思い出しました
ファクトリパターン
最初は、ファクトリパターンである、ファクトリクラスを構築するコードを見て、これは書くための一つの方法である、ファクトリパターンにもつれていないことです。
1 クラスのMyClass <T、TFactory> 2 TFactory:IFactoryです<T>、新しい() 3 { 4つの公共 MyClassの(文字列要求) 5 { 6 VARの工場= 新しいTFactory()。 7 8 この .MyObject = factory.New(リクエスト)。 9 } 10 11 T MyObjectに{ 得ます。セット; } 12 } 13 14 インターフェース IFactoryです<T> 15 { 16 T新(文字列リクエスト)。 17 }
実装は、あなたがいることがわかります、それ自体では一般的な意味はそれほど大きくないとして、この必要性は、各派生クラスまたはインスタンスのカテゴリを作成して、ファクトリクラスを維持するために、それは常に再利用ロジックの種類やジェネリック医薬品の使用を削減することでした。
抽象基底クラスの静的抽象メソッド
あなたはマルチクラスを維持したくない場合は、ターゲット・クラスが開始しているので、私たちは、ターゲットクラスの基本クラスを作成することができます。
1 クラス MyClassの<T> 2 T:TBASE、新しい() 3 { 4つの公共 MyClassの(文字列要求) 5 { 6 本 .MyObject = T.New(リクエスト)。 7 } 8 9 T MyObjectに{ 得ます。セット; } 10 } 11の12 抽象クラスはTBASE 13 { 14 パブリック抽象静的 TBASE新しい(文字列リクエスト)。 15 }
満ち防ぐために、言うべき最初の事は進んでいる、それは間違ってコンパイル書きます!
制約が間違っていないですが、それが報告されたエラーに似ている「T typeパラメータであるので、使用することはできません!」(「T」の指定されたコンテキストで有効でない「タイプのパラメータ」、です)。
コンストラクタからの着信
そこの基本的なアプローチでもあるが、で忘れJames.Ying考えて思い出し、ジェネリッククラスのコンストラクタから渡されます。
クラス MyClassの<T> ここで、 T:TBASE、新しい() { 公共MyClassの(T myObjectという) { この .MyObject = myObjectという。 } T MyObjectに{ 得ます。セット; } }
逆さまにほとんど依存して、発信者にジェネリッククラスより簡潔、インスタンス化プロセスは、(実際には、実装され、ジェネリックで発信者または後継者に引き渡されるべきものすべてが、このようなものだった)よう。
利点は、一般的なシンプルで、欠点は、コンストラクタを使ってインスタンス化することを保証できないことであるT(文字列)です。また、コードの再利用性を減少させることができます。条件、および論理的なすべての派生クラスの仮想的な例は、一般的な基底クラスに達成するためにまだ良いです、均一です。
簡単な例では、これは最もエレガントな方法のための一般的です。
Activator.CreateInstance
この方法は、することができhttp://msdn.microsoft.com/en-us/library/system.activator.createinstance(v=vs.110).aspxそれがより明確であることを示す、見て:
最も一致するコンストラクタを持つ型のインスタンスを作成します(最高指定されたパラメータに一致するコンストラクタを使用して、指定された型のインスタンスを作成します)。
ライティングも非常に興味深いです。
クラス MyClassの<T> { 公共 MyClassの(文字列リクエスト) { この .MyObject =(T)Activator.CreateInstance(typeof演算(T)、リクエスト)。 } T MyObjectに{ 得ます。セット; } }
このアプローチは行うことができ、かつ非常に短いが、それはより多くのインタフェースと基底クラスを行いません。
欠点は、Tは、パラメータの指定された数とタイプを持つコンストラクタ、またはコンストラクタが存在するかどうかをすることができることを保証する方法がない、結合ではありません。
Tは、設計要件を満たしていない場合場合は報告されます適切な例外。
オリジナルのジェネリック型パラメータがそのように設計されて
この時点で、我々は知っているだろう、C#は、ジェネリック型パラメータは「非クラス」の存在、制約型パラメータ(型パラメータの制約)は、単に特定のインスタンス化時に必要なクラスや継承を記述するために使用されています条件を達成。ジェネリック型パラメータの内部には、それは単にクラスを記述するために使用される「特別な存在」、ですが、このクラスを使用することはできません。
その後、型パラメータは......と題した基準紙を持つことができます......
まず、実際には、問題自体は、ジェネリック型パラメータであるようなパラメータ、と道の例を持つことができる T myObjectという= 新しい新しい T(「Hello Worldの!」) 。
次いで、それはジェネリック型パラメータ問題となるようにパラメータタイプは、クラスのインスタンスの特性方法を説明するために「結合」であるので、パラメータコンストラクタ制約方法を有することができる、など WHERE T:新新(文字列) 。
想定しています、そして、それはそれは、原則として、任意の質問を引き起こすかどうかを証明するために存在し、最初の問題の改ざんです。
最初のコンストラクタのパラメータと、どのようにしてジェネリック型パラメータの制約モードがあっても、その後、引数なしのコンストラクタを持つ方法をジェネリック型パラメータを比較することでバインドされていますか?任意の引数のコンストラクタは、ジェネリック型パラメータのコンストラクタ制約的に証明し、すべての問題を引き起こすことはありませんし、技術的に実現可能であることなく、少なくとも、ジェネリック型パラメータがバインドされています。(......)
新しいオブジェクトの例では、通常は2通りの方法で時に初期化されます。
- コンストラクタのパラメータ渡しを使用します
- 割り当てをインスタンス化した後、
ほとんどの場合、結果はほぼほとんどの場合、一般的な特性またはパラメータが(パブリック)、元々のオープンリーディング、ライティング、内部および外部ライトライトに開示されている関係を意味する2つの方法で製造されます彼らは似ています。
しかし、このようなパラメータを使用して動作するために必要ないくつかのビジネス上の制約、またはプロセスパラメータとして、いくつかの例を、遭遇し、最終的に演算結果が(プライベート)プライベートで、それはコンストラクタのパラメータの引き渡しを選択する傾向があります。または、特別な方法を使用するデータクラスによってプロセスがインスタンス化された後、次に操作するために必要なもたらした、「コヒーレント」さわやか下にほとんどありません。
それが属しているほとんどのシナリオで最適なソリューションであるため、コンストラクタのパラメータ渡しを使用すると、簡単な代替方法ではありません。時には、取引自体は、強い原子性があるので1内のすべてのは、最高で、使用するオブジェクトを初期化します。開発者のために、2つの実装のために、オブジェクトを初期化する方法の二種類は、あなたが正確に把握できない二つの方法で生成された結果、あなたは時々ぼやけ、クラスのユーザーとして二重のエントリに問題がありました仕様はまた、必要でいずれかを選択するか、または両方が一貫性を確保するために表示されます。クラスは比較的複雑になると、物事はそう単純ではありません。
だから、私たちは本当にバウンド的コンストラクタのパラメータの数とのシーンがありますジェネリック型パラメータを必要としています。それは必要ありませんが、それは間違いなく必要ですが、のような/そのアクセサを設定します。
さらに、実際には大きな命題は、引数の型がクラスとして使用することができますです
これは、制約としてクラスとしてそれを使用するよう、あなたが指示することができ、パラメータを持つコンストラクタによってその制約を仮定することができますか?例えば、静的メソッドを呼び出しますか?ジェネリックで型パラメータを継承するクラスを作成しますか?
これらの演算子はすべて、単純な実装を解決できるのではなく、すべての特別な場合には見つけられそうです。
例えば、それは静的メソッドを呼び出すTに関与する場合、T.Hello()が実行されることができ、明らかにどのクラスとクラスを作成パラメータジェネリッククラスに複雑になるのタイプから継承します。
ただ、このクラスのメソッドを呼び出すことについて考える:「単なる一般的な問題そのもの」のMyClass <T> .MySubClass、文法ここではビット「珍しい」、およびではないかもしれません
彼は、それは、少し、より多くの機能により、高い力グリッドはC#またはいずれかの言語のための正しい道であることを特徴としますか?
トピックに関する
あなたが不満を持っている場合、彼らは攻撃する任意の方法で禁止され、適切なタイトル、作者を提供することができます!