Initializing a Generic Variable from a C# Type Variable

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.

Initialize a Generic Type property

You can add a new() constraint on T, this makes sure that only types that have a public parameterless constructor can be used as type argument:

public class Payload<T> where T: new() {

public T Result { get; set; } = new T();

public Payload() { }

}

More info: new constraint (C# Reference)

Initialize a generic class with the generic type as a variable

It's possible, but you have to use reflection:

Type genericTypeDefinition = typeof(Rule<>);
Type genericType = genericTypeDefinition.MakeGenericType(_type);
Rule[] array = (Rule[])Array.CreateInstance(genericType, 0);

How to initialize generic parameter type T?

You have two options:

You can constrain T: you do this by adding: where T : new() to your method. Now you can only use the someMethod with a type that has a parameterless, default constructor (see Constraints on Type Parameters).

Or you use default(T). For a reference type, this will give null. But for example, for an integer value this will give 0 (see default Keyword in Generic Code).

Here is a basic console application that demonstrates the difference:

using System;

namespace Stackoverflow
{
class Program
{
public static T SomeNewMethod<T>()
where T : new()
{
return new T();
}

public static T SomeDefaultMethod<T>()
where T : new()
{
return default(T);
}

struct MyStruct { }

class MyClass { }

static void Main(string[] args)
{
RunWithNew();
RunWithDefault();
}

private static void RunWithDefault()
{
MyStruct s = SomeDefaultMethod<MyStruct>();
MyClass c = SomeDefaultMethod<MyClass>();
int i = SomeDefaultMethod<int>();
bool b = SomeDefaultMethod<bool>();

Console.WriteLine("Default");
Output(s, c, i, b);
}

private static void RunWithNew()
{
MyStruct s = SomeNewMethod<MyStruct>();
MyClass c = SomeNewMethod<MyClass>();
int i = SomeNewMethod<int>();
bool b = SomeNewMethod<bool>();

Console.WriteLine("New");
Output(s, c, i, b);
}

private static void Output(MyStruct s, MyClass c, int i, bool b)
{
Console.WriteLine("s: " + s);
Console.WriteLine("c: " + c);
Console.WriteLine("i: " + i);
Console.WriteLine("b: " + b);
}

}
}

It produces the following output:

New
s: Stackoverflow.Program+MyStruct
c: Stackoverflow.Program+MyClass
i: 0
b: False
Default
s: Stackoverflow.Program+MyStruct
c:
i: 0
b: False

How to initialize generic local variable?

Ignoring the other issues with your code, you can't do what you're trying to do. C# does not support arithmetic operators on generic types.

Therefore, one option will be to Sum(del<int>, ..), Sum(del<float>, ...).. etc.

Or, use dynamic:

delegate T del<T>(T x);
static T Sum<T>(del<T> df, IEnumerable<T> data)
{
dynamic s = default(T);
foreach (var x in data) s += df(x);
return s;
}

This results is 30 for your provided example.

how create a generic method that can initialize value variable to 0 or ref variable to new (not null)

You can use the new() constraint:

private V Func<V>() where V : new()
{
// do stuff
V res = new V();
// more stuff
return res;
}

Value types will be initialized to all-zeros, and any reference types will be initialized using their no-args default constructor.

If the reference type doesn't have a no-args constructor it can't be used with this method, and you'll have to use other ways (there are plenty of solutions to this problem elsewhere on SO, eg Passing arguments to C# generic new() of templated type)

Instantiate generic type from variable

The error is self descriptive, you need concrete types to create an instance. Instead of IList (Which has no implementation and is just a contract), you need to use an implementation of IList:

Type genericType = typeof(List<>);
Type[] listOfTypeArgs = new[] { typeof(TabViewModel) };
var newObject = Activator.CreateInstance(genericType.MakeGenericType(listOfTypeArgs));

Edit:

If you don't have a concrete type, you need to get it either using a container or reflecting the current assemblies. Below is a bit of a hack that you need to tweak the way you find useful for your case.

Type genericType = typeof(List<>);
Type concreteType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => genericType.IsAssignableFrom(p)).FirstOrDefault();

Type[] listOfTypeArgs = new[] { typeof(TabViewModel) };
var newObject = Activator.CreateInstance(concreteType.MakeGenericType(listOfTypeArgs));

C# How to Initialize Generic class with object of type Type

You want Type.MakeGenericType and then Activator.CreateInstance... but then calling a method on the newly-created object will be tricky. Ideally you could have a non-generic base class or interface containing those members:

public interface IFoo
{
void CallSomeMethod();
}

public class MyGenericClass<T> : IFoo
{
...
}

// Names changed to be more conventional
public void DoSomething(Type type)
{
var genericType = typeof(MyGenericClass<>).MakeGenericType(type);
var instance = (IFoo) Activator.CreateInstance(genericType);
instance.CallSomeMethod();
}

If you do need to call a method which depends on the type parameter, you'll need to do that with reflection, or with dynamic which can streamline reflection-based code.

EDIT: As cdhowie says, if you always actually do know the type at compile-time, you can use a generic method which would make things much simpler. You'd then call the method like this:

DoSomething<int>();
DoSomething<MyClassA>();
DoSomething<MyClassB>();

initialize value to a public variable of type list of a class using the object initializer

It gives you an error because allData field is of type List<Student> in case of GenericStore<Student>, so in order to seed that field in object initializer you need to instantiate List<Student> collection and use its object initializer to add Student objects

GenericStore<Student> store = new GenericStore<Student>
{
allData = new List<Student>
{
new Student(new Guid(), "Subhashis Pal"),
new Student(new Guid(), "x"),
new Student(new Guid(), "Y"),
new Student(new Guid(), "Z")
}
}


Related Topics



Leave a reply



Submit