将类引用作为构造函数参数传递

时间:2017-01-12 21:24:32

标签: c#

我正在尝试建立一个简单配方列表,它将基本上跟踪一系列“成分”及其生产的产品。

我的问题是,对于我的Recipe类,我更愿意传递代表最终产品的类而不是它的实例。我对C#中的泛型和传递类型不熟悉,所以我正在寻找建议。

如果我有:

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

我想传递类,而不是实例。

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

唯一需要注意的是,它不能泛型,每个参数必须是Food类型。

只有在要求食谱“生成”产品实例时,才会调用Activator.CreateInstance

我主要希望避免发送一个实例,因为我必须克隆它而不是实例化它。

2 个答案:

答案 0 :(得分:1)

您可以在定义Recipe类时使用泛型,并将泛型类型约束到Food类或从Food派生的类。

来自MSDN文档:

  

定义泛型类时,可以对其应用限制   客户端代码可用于类型参数的各种类型   实例化你的类。如果客户端代码试图实例化您的   通过使用约束不允许的类型,结果   是一个编译时错误。这些限制称为约束。   使用where contextual关键字指定约束。该   下表列出了六种类型的约束:

在该文章的下方是一个表,它指定了如何实现所需的结果。在您的情况下,您的食谱声明将如下所示:

public class Recipe<T> where T : Food,可以像往常一样定义构造函数

new Recipe(params string[] ingredients)注意没有打电话给面包。

当您实例化食谱时,您可以使用var recipe = new Recipe<Bread>(ingredientsList)

如果您尝试使用不会从食物中获取的食谱来声明食谱,您将在设计时获得异常,这将通知您

  

该类型不能用作类型参数&#39; T&#39;在通用   方法类型&#39;食谱&#39;。没有拳击转换    去食物&#39;。

如果您需要有关泛型的帮助,这篇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)这样的构造函数,并按照this SO方法中的方法进行操作。这样你就可以了存储类型。

答案 1 :(得分: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)}.");
        }
    }
}

修改

正如@BenVogit在评论中提到的那样,如果你不希望Recipe携带一个类型参数但又想要类型安全,你也可以使工厂方法通用。