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.
Generics in C#, using type of a variable as parameter
The point about generics is to give compile-time type safety - which means that types need to be known at compile-time.
You can call generic methods with types only known at execution time, but you have to use reflection:
// For non-public methods, you'll need to specify binding flags too
MethodInfo method = GetType().GetMethod("DoesEntityExist")
.MakeGenericMethod(new Type[] { t });
method.Invoke(this, new object[] { entityGuid, transaction });
Ick.
Can you make your calling method generic instead, and pass in your type parameter as the type argument, pushing the decision one level higher up the stack?
If you could give us more information about what you're doing, that would help. Sometimes you may need to use reflection as above, but if you pick the right point to do it, you can make sure you only need to do it once, and let everything below that point use the type parameter in a normal way.
C#, instantiating a generic type - with variable type argument?
You just can't use C# generics the way you're trying to do in your snippet.
In order to use [C#] generics, the actual object type must be known at compile time.
You're trying to dynamically pass the object type as a type parameter. This is simply not possible.
Edit
Yes, it is possible to dynamically create generic objects using reflection. After all, generics is implemented both as a compile-time C# construct and as a .NET framework feature (as opposed to, say, Java, where it is only a compile-time feature based on Type Erasure). So, in .NET, through reflection, it is possible to implement the latter "bypassing" the former (which, again, would be impossible in Java).
But the OP clearly does not need that.
After all, entries
is a List<IEntry>
. IOW, the entries
container does not "know" the concrete type of its elements (since it is bound to an interface). So, if each element to be add already implements IEntry
, then this would be enough:
void Foo(params IEntry[] objects)
{
var entries = new List<IEntry>();
foreach(var o in objects)
{
entries.Add(o);
}
...
}
OTOH, if those objects do not implement IEntry
, then the OP just need a pure, ordinary, old-school list of untyped objects:
void Foo(params object[] objects)
{
var entries = new List<object>();
foreach(var o in objects)
{
entries.Add(o);
}
...
}
So using reflection in order to dynamically create a generic container, even if possible, seems to be overkill for this particular use case.
Using a Type Variable in a Generic
Swift's static typing means the type of a variable must be known at compile time.
In the context of a generic function func foo<T>() { ... }
, T looks like a variable, but its type is actually known at compile time based on where the function is called from. The behavior of Array<T>()
depends on T
, but this information is known at compile time.
When using protocols, Swift employs dynamic dispatch, so you can write Array<MyProtocol>()
, and the array simply stores references to things which implement MyProtocol
— so when you get something out of the array, you have access to all functions/variables/typealiases required by MyProtocol
.
But if t
is actually a variable of kind Any.Type
, Array<t>()
is meaningless since its type is actually not known at compile time. (Since Array
is a generic struct, the compiler needs know which type to use as the generic parameter, but this is not possible.)
I would recommend watching some videos from WWDC this year:
- Protocol-Oriented Programming in Swift
- Building Better Apps with Value Types in Swift
I found this slide particularly helpful for understanding protocols and dynamic dispatch:
Calling generic method with Type variable
Lets assume that Foo is declared in class Test such as
public class Test
{
public void Foo<T>() { ... }
}
You need to first instantiate the method for type bar
using MakeGenericMethod. And then invoke it using reflection.
var mi = typeof(Test).GetMethod("Foo");
var fooRef = mi.MakeGenericMethod(bar);
fooRef.Invoke(new Test(), null);
How can I cast a variable to generic type in Dart?
Dart does not provide a way to go from an object of type X
to a type variable bound to X
. There are good technical reasons for not allowing that (it allows the web compilers to know at compile-time which types can ever be bound to a type variable, which allows it to reduce the compiled code).
The dispose
method is treating the type argument as its only argument and acting on the value of that type argument.
It makes me think you're trying to do something that the language is not designed for.
You're passing in a type argument, and then the code inspects that type of argument and behaves differently depending on the value. That's not what's usually meant by being "generic" - to act the in the same (generic) way independently of the types, so the only real effect of passing a type is to make the return type match the argument type.
(That's why Java can erase type arguments at run-time).
So, if you need to know a type for some object, either that object must provide it for you, or you have to store it from earlier (perhaps when the object was created).
So, if you really need to access the type argument that the cubit is implementing Cubit<X>
of, the Cubit
class needs to make it available to you. That will usually be with a method with a callback (like a visitor), something like:
abstract class Cubit<T> ... {
...
R visit<R>(R Function<C extends Cubit<T>, T>(C value) action);
}
class SomeCubit<T> extends Cubit<T> {
...
R visit<R>(R Function<C extends Cubit<T>, T>(C value) action) =>
action<SomeCubit<T>, T>(this);
}
If something like that's available, then you can do what you want as:
bloc.visit(<C extends Cubit<T>, T>(_) => BlocManager.instance.dispose<C>());
If something like that is not available, then you are in trouble.
You can detect a number of known types, with a bunch of if
statements, but that's unlikely to be sufficient.
That means you need to remember the type from earlier, but since it looks like you just get a List<Cubit<Object>>
that has already been created, that doesn't seem practical either.
If the BlocManager
is your own class, consider changing it to use Type
objects instead of type arguments (which is contrary to everything I usually say you should do), because then you can call ..dispose(bloc.runtimeType)
. I'd prefer to avoid that, but if other constraints make what you do impossible, then it might be the lesser evil.
Related Topics
Wait Until Swift For Loop With Asynchronous Network Requests Finishes Executing
Trying to Understand Asynchronous Operation Subclass
How to Resolve: 'Keywindow' Was Deprecated in iOS 13.0
Alternative to Performselector in Swift
Swiftui: How to Make Textfield Become First Responder
Waiting Until the Task Finishes
Passing an Array to a Function With Variable Number of Args in Swift
How to Enumerate an Enum With String Type
How to Dispatch_Sync, Dispatch_Async, Dispatch_After, etc in Swift 3, Swift 4, and Beyond
Instantiated Optional Variable Shows as Nil in Xcode Debugger
How to Create Usdz File Using Xcode Converter