Why won't generic accept type param?

  • Thread starter Thread starter Brad Wood
  • Start date Start date
B

Brad Wood

The following works fine; passing a type to CreateInstance:
private Type _next;
BaseWizardForm nextForm = (BaseWizardForm)Activator.CreateInstance(
_next );

So why doesn't this work (error = _next' is a 'field' but is used like a
'type'):
BaseWizardForm nextForm =
(BaseWizardForm)Activator.CreateInstance<_next>();

_next *is* a type...

And this gives the error "type or namespace name 'corndog' could not be
found.":
Type corndog = typeof(WelcomeForm);
BaseWizardForm nextForm =
(BaseWizardForm)Activator.CreateInstance<corndog>();

It gives that error on the second line...
 
_next *is* a type...

Actually it's an instance of System.Type, something only known at
runtime. That's not what the compiler considers to be a type. So you
have to use Reflection to construct the generic type at runtime.


Mattias
 
Brad Wood said:
The following works fine; passing a type to CreateInstance:
private Type _next;
BaseWizardForm nextForm = (BaseWizardForm)Activator.CreateInstance(
_next );

So why doesn't this work (error = _next' is a 'field' but is used like a
'type'):
BaseWizardForm nextForm =
(BaseWizardForm)Activator.CreateInstance<_next>();

_next *is* a type...

And this gives the error "type or namespace name 'corndog' could not be
found.":
Type corndog = typeof(WelcomeForm);
BaseWizardForm nextForm =
(BaseWizardForm)Activator.CreateInstance<corndog>();

It gives that error on the second line...

You're trying to give information at runtime which the compiler needs
at compile time. It's like trying to use:

Type corndog = typeof(WelcomeForm);
corndog f = new corndog();

The compiler doesn't know what type you're talking about, so it can't
do the *compile-time* checks/references it needs to.
 
Jon Skeet said:
You're trying to give information at runtime which the compiler needs
at compile time. It's like trying to use:

Type corndog = typeof(WelcomeForm);
corndog f = new corndog();

The compiler doesn't know what type you're talking about, so it can't
do the *compile-time* checks/references it needs to.

This is my understanding of how it works (correct me if i'm wrong). If you
use a generic class many times but only with int and string then the
compiler will compile 2 seperate copies of the class, one as if the
appropriate fields/params etc had been defined as int and the other as if
they had been defined as string. Because of this it can't take the type at
runtime.

Michaek
 
Michael said:
This is my understanding of how it works (correct me if i'm wrong). If you
use a generic class many times but only with int and string then the
compiler will compile 2 seperate copies of the class, one as if the
appropriate fields/params etc had been defined as int and the other as if
they had been defined as string. Because of this it can't take the type at
runtime.

No, the compiler doesn't create the copies of the class - the CLR does,
and indeed you *can* create generic classes using reflection at
runtime. The problem is that the compiler wants to know about the type
at compile-time - it just doesn't have enough information to work on in
the above scenario.

Jon
 
Mattias Sjögren said:
Actually it's an instance of System.Type, something only known at
runtime. That's not what the compiler considers to be a type. So you
have to use Reflection to construct the generic type at runtime.

Then I have no idea why Activator has a generic overload. Or maybe I'm just
completely confused. It seems you would always want to pass to Activator a
Type variable rather than explictly referring to the class name. If you
know the class name at compile time, you would just use it's constructor,
not Activator. Right?
 
Brad,
Then I have no idea why Activator has a generic overload. Or maybe I'm just
completely confused. It seems you would always want to pass to Activator a
Type variable rather than explictly referring to the class name. If you
know the class name at compile time, you would just use it's constructor,
not Activator. Right?

One reason for the generic Activator.CreateInstance method is in fact
to implement the new operator. This code

class Foo<T> where T : new() {
T t = new T();
}

compiles to

class Foo<T> where T : new() {
T t = Activator.CreateInstance<T>();
}


Mattias
 
Mattias Sjögren said:
One reason for the generic Activator.CreateInstance method is in fact
to implement the new operator. This code

class Foo<T> where T : new() {
T t = new T();
}

compiles to

class Foo<T> where T : new() {
T t = Activator.CreateInstance<T>();
}

I think it took this example for the light bulb to go off in realizing the
difference between compile time substitiution of generic arguments and run
time evaluation of type variables...
 

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

Back
Top