我有一个接口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
}。怎么去呢?
答案 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() { }