Creating a Generic<T> Type Instance with a Variable Containing the Type

Creating a Generic T type instance with a variable containing the Type

Yes, there is:

var genericListType = typeof(List<>);
var specificListType = genericListType.MakeGenericType(typeof(double));
var list = Activator.CreateInstance(specificListType);

Create instance of generic class with dynamic generic type parameter

I found very simple solution to problem. There is no need to cast object to specific type T, just use dynamic keyword instead of casting

   Type myGeneric = typeof(MyComparer<>);
Type constructedClass = myGeneric.MakeGenericType(T);
object created = Activator.CreateInstance(constructedClass);
dynamic comparer = created; // No need to cast created object to T

and then I can use comparer normally to call its methods like:

   return comparer.Equals(myResultAsT, correctResultAsT);

According to LueTm comments, it is probably possible to use reflection again and call comparer methods, but this solution looks much easier.

Create instance of generic type whose constructor requires a parameter?

Additionally a simpler example:

return (T)Activator.CreateInstance(typeof(T), new object[] { weight });

Note that using the new() constraint on T is only to make the compiler check for a public parameterless constructor at compile time, the actual code used to create the type is the Activator class.

You will need to ensure yourself regarding the specific constructor existing, and this kind of requirement may be a code smell (or rather something you should just try to avoid in the current version on c#).

Create Instance of Generic Type

You should use: CreateInstance(typeof(T)), typeof returns an object of class System.Type which will work.

There is a difference in C# between a 'Generic' type T and an instance of System.Type. Activator.CreateInstance requires the latter.


Edit: You should generally use DavidG's method, it is cleaner. You can use the Activator when:

  • You can't add a generic constraint for some reason.
  • You want to pass arguments to the constructor. (the new() constraint implies a parameterless constructor, with the Activator you can pass parameters.)

Initializing a Generic variable from a C# Type Variable

What you mean by this part is possible:

new AnimalContext<a.GetType()>();

Obviously that exact syntax is wrong, and we'll get to that, but it is possible to construct an instance of a generic type at runtime when you don't know the type parameters until runtime.

What you mean by this part is not:

AnimalContext<a.GetType()> a_Context

That is, it is impossible to type a variable as a generic type if you don't know the type parameters at compile-time. Generics are compile-time constructs, and rely on having the type information available at compile-time. Given this, you lose all the benefits of generics if you don't know the types at compile-time.

Now, to construct an instance of a generic type at runtime when you don't know the type until runtime, you can say:

var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);

Note that the compile-time type of a_context is object. You will have to cast a_context to a type or interface that defines the methods you need to access. Often what you'll see people do here is have the generic type AnimalContext<T> implement some interface (say IAnimalContext) or inherit from a non-generic base class (say AnimalContext) that defines the methods they need (so then you can cast a_context to the interface or the non-generic base class). Another alternative is to use dynamic. But again, keep in mind, you have none of the benefits of generic types in doing this.

How to create instance of class by type with a generic

EDIT: If the set in question had an appropriate constructor, you could use Type.MakeGenericType to create the relevant constructed type and call the constructor using Activator.CreateInstance:

Type albumType = dbSetType.MakeGenericType(typeof(Album));
Albums = (IDbSet<Album>) Activator.CreateInstance(albumType);

Alternatively, you could pass in a DbSetProvider (or whatever) which had a generic method:

public IDbSet<T> CreateDbSet<T>()

then you'd have a ProductionDbSetProvider and a FakeDbSetProvider:

public MusicStoreContext(DbSetProvider provider)
{
Albums = provider.CreateDbSet<Album>();
Artists = provider.CreateDbSet<Artist>();
}

Personally that feels cleaner to me, but YMMV.

Why can't you create an instance of a generic type using new operator?

Short answer:
Java is a compiled programming language, which means that your bytecode is constant at runtime. It is impossible to generate bytecode for new E() if E is unknown.

Explanation: Generic information is erased in runtime:

public class Container<E> {
private E item;
public E getItem() {return item;}
}
class BoxWithPresent extends Container<Present> {
}
class SimpleBox extends Container {
}

In bytecode class BoxWithPresent contains field item of type Present, but class SimpleBox contains field item of type Object (because type E was not specified).

Now you write abstract instantiation method:

public class Container<E> {
public <E> E createE() {
return new E(); // imagine if that was allowed
}
}

What bytecode should be generated here? .class file is generated right now, at compilation time, but we have no idea what is E type.

So.. can new T() be replaced with new Object()? Bad idea, class BoxWithPresent won't like it, because it expects that E is Present.

Can it be replaced with class.newInstance()? Again no, there is no class variable in method scope.

That's why new E() is impossible.

But there are workarounds with passing class as parameter, or extracting generic information.



Related Topics



Leave a reply



Submit