1

I have an abstract base class and a derived class. Let us call them Base and Derived.

Base has the constructor:

public Base(int number)
{
    // do something with number
}

and the Derived class will always have the constructor (even though this cannot be ensured through an interface, this is nevertheless the case in my program):

public Derived(int number) : base(number)
{
    // do some other stuff
}

Now, I would like a factory method to create objects derived from Base, which should be called like this:

Base.Create<Derived>(someNumber);

But I do not know how to implement this method in a correct fashion. I think the most elegant solution would be to do something like this:

public static T Create<T>(int number) where T : Base, new(int)
{
    return new T(number);
}

But it seems that C# does not support the parameterized constructor constraint new(int), only the parameterless one. This solution would have been so clear and it expresses exactly what I want. Oh well..

Instead, I could basically switch on the type parameter and create and instance of the correct type like this:

public static Base Create<T>(int number) where T : Base, new(int)
{
    if (typeof(T) == typeof(Derived))
    {
        return new Derived(number);
    }
    // and so on for all other derived types
}

But this requires me to update the method every single time I make a new derived class, which is unfortunate. Besides, typeof(T) == typeof(Derived) seems way too hackish. Also, with this approach it seems the return type of the factory method will have to be Base instead of T, which is also unfortunate. I could just as easily resort to using enums instead of a type parameter in that case.

I wonder if there is a better way to achieve what I want?

Community
  • 1
  • 1
Thorkil Holm-Jacobsen
  • 7,287
  • 5
  • 30
  • 43

1 Answers1

4

You can use an Activator to create an instance:

public static T Create<T>(int number) where T : Base
{
    return (T) Activator.CreateInstance(typeof (T), number);
}

In this case you will not need to update the method if you create a new derived class. This assumes that you always have a constructor which takes a single integer parameter. If such constructor does not exist you will get a runtime exception.

dotnetom
  • 24,551
  • 9
  • 51
  • 54