[英]Is there a way to enforce parameterless constructor without generic constraint
I have an interface ISnack
which when implemented by a class, it should have a default parameterless constructor. 我有一个接口ISnack
,当由类实现时,它应该有一个默认的无参数构造函数。 Basically this: 基本上这个:
public interface ISnack<T> where T : new()
{
}
I use <T> where T : new()
just to enforce the parameterless constructor. 我使用<T> where T : new()
只是为了强制执行无参数构造函数。
I would then implement the interface this way: 然后我会以这种方式实现接口:
public class Cutlet : ISnack<Cutlet>
{
}
This works and it simply ensures Cutlet
class has a parameterless constructor. 这有效,它只是确保Cutlet
类具有无参数构造函数。
Now I have an abstract base class Kitchen
: 现在我有一个抽象基类Kitchen
:
public abstract class Kitchen<T> where T : ISnack
{
}
The requirement is that Kitchen
should have constraint where T
should be an ISnack
. 要求是Kitchen
应该有一个约束,其中T
应该是一个ISnack
。 But this wont work because there exists no ISnack
, but only ISnack<T>
. 但这不会起作用,因为没有ISnack
,只有ISnack<T>
。
If I tried this 如果我试过这个
public abstract class Kitchen<T> where T : ISnack<T>
{
}
it wouldn't compile ( '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>'
) and also wouldn't make sense in my context. 它不会编译( '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>'
)并且也不会在我的背景下感觉。
If I could force ISnack
s to have a parameterless constructor without constraining by a T
type parameter, then T
in Kitchen<T>
could easily be an ISnack
. 如果我能迫使ISnack
s至具有参数的构造函数而不受约束T
类型参数,然后T
在Kitchen<T>
很容易被一个ISnack
。 How to go about it? 怎么去呢?
You can't unless you add the constraint; 除非添加约束,否则不能; generic constraints are cumulative, so to make the compiler happy you would have to have: 泛型约束是累积的,因此要使编译器满意,您必须具有:
public abstract class Kitchen<T> where T : ISnack<T>, new()
If that is fine, then do that . 如果没关系, 那就去做吧 。 If it isn't fine, then you'll have to remove the : new
from the original, and make do without it. 如果它不好,那么你将不得不从原版中删除: new
,并且不使用它。 This isn't as bad as it sounds, but it means you push validation down to execution rather than compilation. 这并不像听起来那么糟糕,但它意味着您将验证推送到执行而不是编译。 But: Activator.CreateInstance<T>()
still does what you would need, anyway - even without the new()
constraint. 但是:即使没有new()
约束, Activator.CreateInstance<T>()
仍然会做你需要的东西。 So you can replace: 所以你可以替换:
T newObj = new T(); // validated by the compiler
with: 有:
T newObj = Activator.CreateInstance<T>(); // not validated until executed
A handy trick when removing constraints can be: add a unit/integration test that finds the candidate types via reflection, and validate the missing constraint as part of your test suite . 删除约束时的一个方便技巧可以是:添加通过反射查找候选类型的单元/集成测试,并将缺少的约束验证为测试套件的一部分 。
You can use a second generic parameter: 您可以使用第二个通用参数:
abstact class Kitchen<T, S>
where T : ISnack<S>
where S : new()
....
This will solve your issue. 这将解决您的问题。
Adding a second parameter to a class also can cause some issues which i've faced since .NET 2.0 is available. 向类中添加第二个参数也可能导致我在.NET 2.0可用时遇到的一些问题。 Some complex situations may require to add more generic parameters to classes than you like to. 某些复杂情况可能需要向类添加比您更喜欢的更多通用参数。 Normally i break down the generic chain by adding more direct casts ( like (SpecificType)base.MyTypeTProperty
). 通常我通过添加更多直接强制转换(如(SpecificType)base.MyTypeTProperty
)来分解泛型链。 Comment: I try to find a sample later 评论:我试着稍后找一个样本
只需再次将约束添加到T.
public abstract class Kitchen<T> where T : ISnack<T>, new() { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.