Creating instance of Generic type using parametised constructor

Hi,

Why does the code below not work I've constrained the T type of the Bar class to be a "Foo" but I still get compiler error "Error 1 'T': cannot provide arguments when creating an instance of a variable type" (beta 2 - 8.0.50215.44). Since I've constrained T to be a class rather than interface, shouldn't I be able to use the Foo(int) constructor Is there another way of doing the same thing In my case, Foo is an algorithm (i.e a numerical interpolation scheme) and Bar is a data class which I'd like to associate the algorithm with. It seems like a nice way of doing things but it doesn't work :(

Dave



    public class Foo
    {
        public Foo(int i)
        {
            _i = i;
        }

        private int _i;
    }

    public class Bar<T>
    where T : Foo, new()
    {
        public T Create()
        {
            return new T(8);
        }
    }


 



Answer this question

Creating instance of Generic type using parametised constructor

  • dzeaman

    You can't provide arguments to the constructor of a generic type, because the constraint only specifies T should be of type Foo or derived from Foo. A class derived from Foo could have it's very own constructor, adding or removing arguments.



  • cchau

    One of the enhancements I'd like to see to delegates is the ability to specify what constructors T needs to implement like


    public class Bar<T> where T : Foo, new(), new(int)

     


    Unfortunately, as it stands now, the only constructor that you can use is the default constructor.  You COULD do the following...


    public class Foo
    {
       public Foo() {}
       public Foo(int i) { _i = i; }
       public void Initialize(int i) { _i = i; }
       private int _i;
    }

    public class Bar<T> where T : Foo, new()
    {
       public T Create()
       {
          T t = new T();
          t.Initialize(8);
          return t;
       }
    }

     


    but yeah, it's not as pretty as I'd like either.

  • Karel Kruizenruiker

    Thanks for the replies, from http://msdn.microsoft.com/msdnmag/issues/03/10/NET/

    "The constructor constraint makes it possible for generic code to create instances of the type specified by a type parameter by constraining type arguments to types that implement a public default constructor. At this time, only default or parameterless constructors are supported with the constructor constraint."

    The following works as well, but if T were derived from Foo rather than being a Foo it would fail at runtime, doesn't look like you can do T.CreateInstance(8) even though CreateInstance is static, so from what I can gather, the where T:Foo, new() only allows access to Foo's default constructor and non-static methods (i.e. it's really no different to an interface constraint).



        public class Foo
        {
            private Foo(int i)
            {
                _i = i;
            }

            public static Foo CreateInstance(int i)
            {
                return new Foo(i);
            }

            private int _i;
        }

        public class Bar<T>
        where T : Foo, new()
        {
            public T Create()
            {
                return Foo.CreateInstance(8) as T;
            }
        }

     




  • Mithun.Pentuker

    Ahh, yes that works well, I used reflection which works as well but the factory pattern is cleaner. Thanks


        public class Foo
        {
            public Foo(int i)
            {
                this.i = i;
            }

            public int i;
        }

        public class Bar<T>
        where T : Foo
        {
            public T Create(int i)
            {
                return Activator.CreateInstance(typeof(T), new object[] { i }) as T;
            }
        }

     


  • Guddy

    "the constraint only specifies T should be of type Foo or derived from Foo" 

    Not true!  Did you overlook the "new()" constraint   It specifies that T must implement a constructor with no parameters.  The problem is that the "new" constraint doesn't have any options, so we're severely limited in what we can require of T in the way of constructors.

  • theczar

    Of course, you could do...



    public interface IFooFactory<T> where T : Foo
    {
       T CreateInstance(int i);
    }

    public class Foo
    {
       public Foo( int i) {...}
    }

    public class FooFactory : IFooFactory<Foo>
    {
       public FooFactory() {...}
       public Foo CreateInstance(int i) { return new Foo(i); }
    }

    public class Bar<T,U>
    where T : Foo
    where U : IFooFactory<T>, new()
    {
       public T Create()
       {
          return fooFactory.Create(8);
       }

       private U fooFactory = new U();
    }

    OR

    public class Bar<T,U>
    where T : Foo
    where U : IFooFactory<T>
    {
       public Bar( U fooFactory)
       {
             this.fooFactory = fooFactory;
       }

       public T Create()
       {
          return fooFactory.Create(8);
       }

       private U fooFactory = null;
    }

     


  • Creating instance of Generic type using parametised constructor