Question

This isn't legal:

public class MyBaseClass
{
  public MyBaseClass() {}
  public MyBaseClass(object arg) {}
}


public void ThisIsANoNo<T>() where T : MyBaseClass
{
  T foo = new T("whoops!");
}

In order to do this, you have to do some reflection on the type object for T or you have to use Activator.CreateInstance. Both are pretty nasty. Is there a better way?

Was it helpful?

Solution

You can't constrain T to have a particular constructor signature other than an empty constructor, but you can constrain T to have a factory method with the desired signature:

public abstract class MyBaseClass
{
    protected MyBaseClass() {}
    protected abstract MyBaseClass CreateFromObject(object arg);
}

public void ThisWorksButIsntGreat<T>() where T : MyBaseClass, new()
{
    T foo = new T().CreateFromObject("whoopee!") as T;
}

However, I would suggest perhaps using a different creational pattern such as Abstract Factory for this scenario.

OTHER TIPS

Nope. If you weren't passing in parameters, then you could constrain your type param to require a parameterless constructor. But, if you need to pass arguments you are out of luck.

where T : MyBaseClass, new()

only works w/ parameterless public constructor. beyond that, back to activator.CreateInstance (which really isn't THAT bad).

I can see that not working.

But what is stopping you from doing this?

public void ThisIsANoNo<T>() where T : MyBaseClass
{
  MyBaseClass foo = new MyBaseClass("whoops!");
}

Since everything is going to inherit from MyBaseClass they will al be MyBaseClass, right?

I tried it and this works.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ThisIsANoNo<MyClass>();
            ThisIsANoNo<MyBaseClass>();
        }

        public class MyBaseClass
        {
            public MyBaseClass() { }
            public MyBaseClass(object arg) { }
        }

        public class MyClass :MyBaseClass
        {
            public MyClass() { }
            public MyClass(object arg, Object arg2) { }
        }

        public static void ThisIsANoNo<T>() where T : MyBaseClass
        {
            MyBaseClass foo = new MyBaseClass("whoops!");
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top