Generic Constructor Constraints
Here's something I've banged my head against a few times in C# and would love to see a solution for, perhaps in a future version of the language.
Let's say we have a class which requires a constructor parameter, like this:
public class NeedsANumber
{
public NeedsANumber(int number) { ... }
}
You can't create an instance of this class without giving it a number. This might be the base class for a whole hierarchy of classes, like this:
public class NeedsANameAndNumber
{
public NeedsANameAndNumber(string name, int number)
: base(number)
{
...
}
public NeedsANameAndNumber(int number)
: this("Default Name", number)
{
...
}
}
Now we want a generic class which needs to create one of these babies. It might look like this:
public class Factory<T> where T : NeedsANumber
{
public T CreateNew(int number)
{
...
}
}
Now, what should happen in the CreateNew
method?
I can't do this:
return new NeedsANumber(number);
... because I want the returned type to be of type T
, not NeedsANumber
. I can't do this:
return new T(number);
... because I can't guarantee that the derived type T
has a constructor that takes a single int.
What I'd like is the ability to tell my Factory
type that it can only work with classes that have a constructor like that. It'd use the new
generic constraint, like this:
public class Factory<T> where T : NeedsANumber, new(int)
{
public T CreateNew(int number)
{
return new T(number);
}
}
So the new(int)
constraint gives the class all the information it needs about T
to create a new instance.
Right now the only way to get around this that I can think of (short of reflection magic, I suppose) is to ask for a factory lambda:
public class Factory<T> where T : NeedsANumber
{
public Factory(Func<int, T> getNewT)
{
_getNewT = getNewT;
}
Func<int, T> _getNewT;
public T CreateNew(int number)
{
return _getNewT(number);
}
}
... and that's not a bad solution, but a certainly less tidy than a parameterized new
constraint. You'd use the above class like this:
new Factory<NeedsANameAndNumber>(n => new NeedsANameAndNumber("name", n));
Generic constructor constraints would be a welcome addition to the existing generic type constraints provided by C#.
Trackbacks
- rimonabantexcellence site title | http://www.rimonabantexcellence.com/t.php?ahr0cdovl21hdhroyw1pbhrvbi5vcmcvz2vuzxjpyy1jb25zdhj1y3rvci1jb25zdhjhaw50cz9yzxzpc2lvbj0y