2017-01-12 16 views
0

私はシンプルレシピのリストを作成しようとしています。これは本質的に「成分」とそれらが生成する製品のリストを追跡します。コンストラクタ引数としてクラス参照を渡す

私の問題は、私のRecipeクラスでは、私はそのインスタンスではなく最終製品を表すクラスを渡すことを好みます。私はジェネリックスやC#の型を渡すことに慣れていないので、私はアドバイスを探しています。

私が持っている場合:

public class Bread : Food { 
    //... 
} 

私はクラスではなく、インスタンスを渡したいです。

var bread = new Recipe(Bread, ... ingredients);

唯一の注意点は、それがあまりにも総称することはできません、すべての引数はFoodタイプでなければならないということです。

レシピが製品のインスタンスを「生成」するよう要求された後は、Activator.CreateInstanceと呼ぶでしょう。

インスタンスの送信ではなく、複製する必要があるため、主にインスタンスの送信を避けたいと考えています。

+0

「実際に意味をなさないクラス」ではなく「インスタンスを渡したい」。あなたは* something * - インスタンス、 'Type'オブジェクト、文字列、何かを送る必要があります。私は多くの 'Type'sを送信したいと思います。 – Jonesopolis

+0

私の専門用語はC#と正しくマッチしませんが、javaでは' public Recipe(Class product、...) ' – helion3

答えて

1

レシピクラスを定義するときにジェネリックを使用し、ジェネリックタイプをフードクラス、またはFoodから派生したクラスに制限することができます。

あなたはジェネリッククラスを定義するとき、あなたはそれ があなたのクラスをインスタンス化する際に、クライアントコードは型引数に使用できるタイプの 種類に制限を適用することができます:MSDNドキュメントから

。クライアントコードが、制約によって許可されていない型を使用して クラスをインスタンス化しようとすると、結果は となり、コンパイル時エラーとなります。これらの制約は制約と呼ばれます。 制約はwhereコンテキストキーワードを使用して指定します。次の表の には、6種類の制約がリストされています。

この記事のさらに下には、必要な結果を得る方法を指定する表があります。あなたのケースでは、あなたのレシピ宣言は次のようになります。

public class Recipe<T> where T : Food、パンへの呼び出しはありません通常の

new Recipe(params string[] ingredients)予告としてコンストラクタを定義することができました。

レシピをインスタンス化するときは、var recipe = new Recipe<Bread>(ingredientsList)を使用できます。

あなたは食品から派生しないものとレシピを試してみて、宣言した場合、あなたは

型が型として使用することができないことが通知されますされ、設計時中に例外を取得しますがパラメータ 'T'は、メソッド 'Recipe'のタイプ です。 から「食品」へのボクシングの変換はありません。

ジェネリック医薬品に関するヘルプが必要な場合は、こちらのMSDNの記事を参考にしてください。

更新: コメントごとに、これを実装する別の方法は、ジェネリックをCreateメソッドにプッシュすることです。

あなたのコードは次のようになります:

public class Food { } 
public class Bread :Food { } 
public class Recipe 
{ 
    public T Create<T>() where T : Food, new() 
    { 
     return new T(); 
    } 
} 

は、私はまた、新しい制約を追加しました(この場合のインスタンスの静的クラスを渡すため、実行時例外を引き起こすことを必要とします)。レシピをリストに保存できるようになりましたが、レシピ作成時ではなく、オブジェクトの作成時に呼び出す特定のタイプをロジックで提供する必要があります。あなたは、実行時にタイプを決定する場合

(そう基本的にこのpublic Recipe(T typeToCreate)のようにコンストラクタを追加し、後で作成するためのレシピでタイプを保存し、SO this答える方法論に従ってください。これは、タイプを保存することができます。

+0

となります。生成されたオブジェクトが、作成中に渡された型に依存する型を持つ必要がある場合レシピ帳のように、たくさんのレシピをコレクションに入れたい場合は、面倒です。 'Recipe (...)'の代わりに 'Recipe.Create (...)'を使用し、それを 'class Recipe {pubic静的なレシピ作成(...)T:Food {...}} ' –

+0

また、「T:new()」と考えてください。 –

+0

@BenVoigtリストはありますが、問題である。すべてが 'Food'のサブクラスなので' List 'を実行するのは受け入れられません。 – helion3

0

は、次のいずれかを実行できます

public class Recipe<T> where T:Food 
{ 
    public Recipe(params object[] ingredients) 
    { 

    } 
} 

または:

public class Recipe 
{ 
    public Recipe(Type foodType, params object[] ingredients) 
    { 
     if (!foodType.IsSubclassOf(typeof(Food))) 
     { 
      throw new ArgumentException($"{nameof(foodType)} must be a subclass of {nameof(Food)}."); 
     } 
    } 
} 

EDIT:

@BenVogitが彼のコメントで言及したように、Recipeに型パラメータを持ちたいが型の安全性が必要な場合は、ファクトリメソッドをgenericにすることもできます。

+1

2番目のケースのより良い代替案は、一般的なファクトリ関数です( 'Recipe'クラスは依然として一般的ではありません。ファクトリ関数はコンパイル時の型チェックを許可しています) –

関連する問題