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 theActivator
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
How to Run C# Project Under Linux
Why Doesn't .Net/C# Optimize for Tail-Call Recursion
How to Write a JSON File in C#
How to Read a File Even When Getting an "In Use by Another Process" Exception
How to Stop C# Console Applications from Closing Automatically
Free File Locked by New Bitmap(Filepath)
Easiest Way to Create a Cascade Dropdown in ASP.NET MVC 3 with C#
Order of Linq Extension Methods Does Not Affect Performance
.Net Core MAChine Key Alternative for Webfarm
Reading 64Bit Registry from a 32Bit Application
Compiler Ambiguous Invocation Error - Anonymous Method and Method Group with Func<> or Action
Up, Down, Left and Right Arrow Keys Do Not Trigger Keydown Event