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


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

privateint _i;
}

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


[1465 byte] By [DaveWaterworth] at [2008-2-23]
# 1
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.

dkocur2 at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 2

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.

DanielRieck at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 3
"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.

dkocur2 at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 4

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;
}
}

DaveWaterworth at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 5
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;
}

dkocur2 at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 6

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;
}
}

DaveWaterworth at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...