问题
Disclaimer: Theoretical Question
The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor.
Source: http://msdn.microsoft.com/en-us/library/sd2w2ew5(v=vs.80).aspx
What if I wanted my generic class to have a protected parameterless constructor instead? For instance, if I want to write a Singleton
class which I "attach" to other classes to make them Singleton
s, I don't want the derived classes to be instantiable - everything should go through the .Instance
property.
internal class Singleton<T> where T : new()
{
public static T Instance { get; private set; }
static Singleton()
{
Singleton<T>.Instance = new T();
}
}
internal class OnlyOneOfMe : Singleton<OnlyOneOfMe>
{
protected OnlyOneOfMe()
{
}
}
This way, Singleton<T>
is able to create the only instance of the OnlyOneOfMe
class, but nothing else can (unless it is a subclass).
"What if a generic parent class could access the generic type's protected members?"
回答1:
Because that is the definition of the constraint. It's a bit like asking why does T : class
require that T
be a reference type. It's true by definition.
Additionally, if it weren't a public constructor, what would be the point of the constraint? The class receiving the type parameter T
wouldn't be able to call the constructor if it weren't public.
回答2:
You can call a protected constructor using reflection. However this should raise warning signs that you are doing something you are not supposed to. In most cases, you should be able to avoid a singleton and use dependency injection instead. If that doesn't work either, you can use something like the ambient context pattern (see my answer here).
回答3:
If the constructor were protected, Singleton wouldn't be able to call it.
And I'd avoid implementing the singleton pattern like that anyway, even if I could. It's messy - what if you wanted a singleton class that inherits from an abstract one?
回答4:
.NET would not know that you don't want to accept
class OnlyOneOfMe : Singleton<Other>
as a valid class. Since it is actually valid it will try to make the class and needs a public Other constructor.
来源:https://stackoverflow.com/questions/5984152/why-must-the-new-constraint-require-a-public-constructor