Why does the generic constraint new() use Activator<T>.CreateInstance instead of new T()?

M

mjduncan

Why does the generic constraint new() use Activator<T>.CreateInstance
instead of new T()?

An example

public class Foo<T> : where T : class, new()
{
T objectValue = new T();

public foo() {}
}

If you look at Lutz's reflector you will get something like
T objectValue = Activator<T>.CreateInstance() in place of T
objectValue = new T();

Using the Activator class is obviously slower and unintuitive to me,
so why does the framework compile my code using
Activator<T>.CreateInstance() instead of new T()?
 
M

Mattias Sjögren

Using the Activator class is obviously slower and unintuitive to me,
so why does the framework compile my code using
Activator<T>.CreateInstance() instead of new T()?

new T usually compiles to the newobj IL instruction (when T is a
reference type). But newobj doesn't support generic type arguments.


Mattias
 
B

Barry Kelly

Why does the generic constraint new() use Activator<T>.CreateInstance
instead of new T()?

An example

public class Foo<T> : where T : class, new()
{
T objectValue = new T();

public foo() {}
}

If you look at Lutz's reflector you will get something like
T objectValue = Activator<T>.CreateInstance() in place of T
objectValue = new T();

Using the Activator class is obviously slower and unintuitive to me,
so why does the framework compile my code using
Activator<T>.CreateInstance() instead of new T()?

Probably because the compiler hasn't special-cased code generation based
on reference type constraint. It does special-case struct, in which case
it produces initobj rather than calling CreateInstance().

Because of the two different ways of initializing reference types and
value types (first by newobj with constructor argument, second by
initobj), in the most general case of a new() constraint something like
Activator<T>.CreateInstance() is needed.

-- Barry
 
B

Barry Kelly

Mattias said:
new T usually compiles to the newobj IL instruction (when T is a
reference type). But newobj doesn't support generic type arguments.

Actually, the CLR does if you constrain the type argument to reference
types:

..method private hidebysig static void Foo<class .ctor T>() cil managed
// ...
newobj instance void !!T::.ctor()

However, it will not pass PEVerify.

-- Barry
 
L

Laura T.

You can use newobj when you already know the type.
In the case of generics, you are creating a new type (closed type) that
newobj cannot do.
 

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

Top