Home All Groups Group Topic Archive Search About

Generics and constructors.

Author
8 Jan 2007 4:09 AM
Kevin Burton
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

Author
8 Jan 2007 4:23 AM
Carl Daniel [VC++ MVP]
Kevin Burton wrote:
Show quote
> 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
Author
10 Jan 2007 8:07 PM
Ben Voigt
>> 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:
>

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.
Author
10 Jan 2007 8:15 PM
Ben Voigt
Show quote
"Ben Voigt" <rbv@nospam.nospam> wrote in message
news:OuKUeLPNHHA.3952@TK2MSFTNGP02.phx.gbl...
>
>>> 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:
>>
>
> 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);
}
Show quote
>
>    //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.
>

AddThis Social Bookmark Button