Why must the new() constraint require a public constructor?
Disclaimer: Theoretical Question
The new constraint specifies that any type argument in a generic class declarat开发者_JAVA技巧ion 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?"
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.
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).
.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.
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?
精彩评论