Generics and constructors.

G

Guest

There is something that I don't understand about .NET Generics. I have code
like the following:

public class A
{
private string _paramOne;
private string _paramTwo;
public A(string paramOne, string paramTwo)
{
_paramOne = paramOne;
_paramTwo = paramTwo;
}
}

public class GenericA<T> where T : new()
{
public GenericA(string paramOne, string paramTwo)
{
new T(paramOne, paramTwo);
}
}

static void Main(string[] args)
{
GenericA<A> instance = new GenericA<A>("paramOne", "paramTwo");
}


In trying to get the strings to the type specified by the generic type
parameter I get numerous errors mainly focusing on the fact that I either
must define a parameterless construtor or I cannot use parameters in a
constructor. So my question is two fold. How do I get the arguments on the
GenericA<A> constructor to the A class? And, when and how is the type A
instantiated and constructed.

Thank you.

Kevin Burton
 
C

Carl Daniel [VC++ MVP]

Kevin said:
There is something that I don't understand about .NET Generics. I
have code like the following:

public class A
{
private string _paramOne;
private string _paramTwo;
public A(string paramOne, string paramTwo)
{
_paramOne = paramOne;
_paramTwo = paramTwo;
}
}

public class GenericA<T> where T : new()
{
public GenericA(string paramOne, string paramTwo)
{
new T(paramOne, paramTwo);
}
}

static void Main(string[] args)
{
GenericA<A> instance = new GenericA<A>("paramOne",
"paramTwo"); }


In trying to get the strings to the type specified by the generic type
parameter I get numerous errors mainly focusing on the fact that I
either must define a parameterless construtor or I cannot use
parameters in a constructor. So my question is two fold. How do I get
the arguments on the GenericA<A> constructor to the A class? And,
when and how is the type A instantiated and constructed.

You can't. .NET generics constructor constraint only supports a default
constructor - there's no way to invoke any other constructor on the generic
type parameter. The closest you can come is to define an interface and use
two-phase construction:

public interface IStringInit
{
void Init(string p1, string p2);
}

public class X<T> where T: IStringInit, new()
{
public X(string p1, string p2)
{
T t = new T();
t.Init(p1,p2);
}
}

public class A : IStringInit
{
private string _paramOne;
private string _paramTwo;
public void Init(string paramOne, string paramTwo)
{
_paramOne = paramOne;
_paramTwo = paramTwo;
}

static void Main(string[] args)
{
X<A> instance = new X<A>("paramOne", "paramTwo");
}
}


..NET Generics are a great addition, but the need to be fully typesafe at
compile time puts huge limitations on what you can do with them.

-cd
 
B

Ben Voigt

You can't. .NET generics constructor constraint only supports a default
constructor - there's no way to invoke any other constructor on the
generic type parameter. The closest you can come is to define an
interface and use two-phase construction:

The factory pattern seems to be appropriate here. You could always do
something like have a static method that creates the object, and in the type
initializer of your generic class, use reflection to get the MethodInfo and
create a delegate. Then you only have the overhead once per class.

class A
{
private A(string one, string two) { }
public static Create(string one, string two) { return new A(one, two); }
}

class Generic<T>
{
delegate T Factory(string one, string two);
static Factory Constructor;
static Generic()
{
Constructor = Delegate.Create(typeof(Factory), typeof(T), "Create");
}

//instead of T t = new T("A", "B")
T t = Constructor("A", "B");
}

The downside to this is that it's not compile-time checked list generic type
constraints, and calling through a delegate might be a tiny bit slower than
a generic method call. The static constructor is going to be a hog, but it
only runs once for each T you use. You might use lazy initialization if you
don't create new instances of every different T.
 
B

Ben Voigt

Ben Voigt said:
The factory pattern seems to be appropriate here. You could always do
something like have a static method that creates the object, and in the
type initializer of your generic class, use reflection to get the
MethodInfo and create a delegate. Then you only have the overhead once
per class.

class A
{
private A(string one, string two) { }
public static Create(string one, string two) { return new A(one,
two); }
}
Just realized, when using a delegate, there's absolutely zero reason not to
lazily initialize:
class Generic<T>
{
delegate T Factory(string one, string two);
static Factory Constructor = GetFactoryFunctor;
static T GetFactoryFunctor(string one, string two)
{
Constructor = Delegate.Create(typeof(Factory), typeof(T), "Create");
return Constructor(one, two);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top