有没有办法在没有通用约束的情况下强制执行无参数构造函数

时间:2012-10-09 11:31:02

标签: c# generics inheritance interface abstract-class

我有一个接口ISnack,当由类实现时,它应该有一个默认的无参数构造函数。基本上这个:

public interface ISnack<T> where T : new()
{

}

我只使用<T> where T : new()来强制执行无参数构造函数。

然后我会以这种方式实现接口:

public class Cutlet : ISnack<Cutlet>
{

}

这样可以确保Cutlet类具有无参数构造函数。

现在我有一个抽象基类Kitchen

public abstract class Kitchen<T> where T : ISnack
{

}

要求是Kitchen应具有约束,其中T应为ISnack但是这不起作用,因为没有ISnack,只有ISnack<T>

如果我试过这个

public abstract class Kitchen<T> where T : ISnack<T>
{

}

它不会编译('T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ISnack<T>'),也不会在我的上下文中有意义。

如果我可以强制ISnack拥有无参数构造函数而不受T类型参数约束,那么T中的Kitchen<T>很容易成为ISnack }。怎么去呢?

3 个答案:

答案 0 :(得分:12)

除非你添加约束,否则你不能;泛型约束是累积的,因此要使编译器满意,您必须具有:

public abstract class Kitchen<T> where T : ISnack<T>, new()

如果可以, 然后执行 。如果不是很好,那么你必须从原版中删除: new,并且不用它。这并不像听起来那么糟糕,但它意味着您将验证推送到执行而不是编译。但是:Activator.CreateInstance<T>()仍然会做你需要的东西 - 即使没有new()约束。所以你可以替换:

T newObj = new T(); // validated by the compiler

使用:

T newObj = Activator.CreateInstance<T>(); // not validated until executed

删除约束时的一个方便技巧可以是:添加通过反射查找候选类型的单元/集成测试,并验证缺少的约束作为测试套件的一部分

答案 1 :(得分:3)

您可以使用第二个通用参数:

abstact class Kitchen<T, S> 
    where T : ISnack<S> 
    where S : new()
....

这将解决您的问题。

向类中添加第二个参数也会导致一些问题,因为自.NET 2.0可用以来我遇到过这些问题。某些复杂情况可能需要向类添加比您更喜欢的更多通用参数。通常我会通过添加更多直接强制转换(例如(SpecificType)base.MyTypeTProperty)来分解泛型链。 评论:我试图稍后找到一个样本

答案 2 :(得分:1)

只需将约束再次添加到T

public abstract class Kitchen<T> where T : ISnack<T>, new()   {      }