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#.

c# .net generics wishlist
Posted by: Matt Hamilton
Last revised: 10 Oct, 2024 02:04 PM History