So here's what I'm trying to do.
I'm creating a generic class that allocates the type specified by the generic parameter in one of two ways, determined by which overloaded constructor is used.
Here is the example:
class MyClass<T>
where T : class
{
public delegate T Allocator();
public MyClass()
{
obj = new T();
}
public MyClass( Allocator alloc )
{
obj = alloc();
}
T obj;
}
This class requires that type T is a reftype in all cases. For the default constructor, we want to instantiate T via its default constructor. I'd like to put a where T : new()
on my default constructor, like this:
public MyClass()
where T : new()
{
obj = new T();
}
However, this is not valid C#. Basically I only want to add the constraint on type T to have a default constructor only when the default constructor of MyClass() is used.
In the second constructor for MyClass, we let the user determine how to allocate for T with their own allocation method, so obviously it makes sense for MyClass to not enforce T be default constructible in all cases.
I have a feeling that I'll need to use reflection in the default constructor for this, but I hope not.
I know this can be done because the Lazy<T>
class in .NET 4.0 does not require T to be default constructible at the class level, yet it has constructors similar to those in my example. I'd like to know how Lazy<T>
does it at least.
You can only include constraints in the declaration where you're introducing a generic type parameter.
However, you could introduce a generic method on a non-generic type:
public class MyClass
{
public static MyClass<T> Create<T>() where T : class, new()
{
return new MyClass<T>(() => new T());
}
}
public class MyClass<T> where T : class
{
T obj;
public MyClass(Allocator allocator)
{
obj = allocator();
}
}
(I'd personally just use Func<T>
instead of declaring a separate delegate type btw.)
Then you can use:
MyClass<Foo> foo = MyClass.Create<Foo>(); // Enforces the constraint
Basically I only want to add the constraint on type T to have a default constructor only when the default constructor of MyClass() is used.
It is not possible to enforce this with a constraint on T
. You either have it be the case that where T : new()
is specified in the definition of MyClass<T>
or you do without such a constraint at all.
I have a feeling that I'll need to use reflection in the default constructor for this, but I hope not.
You can't enforce the constraint, but you can say
obj = Activator.CreateInstance<T>();
which will invoke the default constructor for T
.
I know this can be done because the Lazy class in .NET 4.0 does not require T to be default constructible at the class level, yet it has constructors similar to those in my example. I'd like to know how Lazy does it at least.
Lazy<T>
requires you specify a delegate that returns instances T
. Basically, it requires you to specify a Func<T>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With