I'm missing a trick here I think and can't believe I've never done this before. However, how can I cast a generic type using the as keyword?
[Serializable] public abstract class SessionManager<T> where T : ISessionManager { protected SessionManager() { } public static T GetInstance(HttpSessionState session) { // Ensure there is a session Id if (UniqueId == null) { UniqueId = Guid.NewGuid().ToString(); } // Get the object from session T manager = session[UniqueId] as T; if (manager == null) { manager = Activator.CreateInstance<T>(); session[UniqueId] = manager; } return manager; } protected static string UniqueId = null; }
The line T manager = session[UniqueId] as T;
throws the following error:
The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint
Now, I think understand the reason for this; I've not physically told the compiler that T is a class. If I replace:
public abstract class SessionManager<T> where T : ISessionManager
with
public abstract class SessionManager<T> where T : class
... then the code builds successfully.
But my question is thus; how can I have both the class and ISessionManager enforcements on the generic type? I'm hoping there's a very simple answer for this.
EDIT: Just to add I had tried: where T : ISessionManager, class
, turns out I hadn't read my compiler error properly. Simply enough, just putting class before ISessionManager
fixes the issue. The error I hadn't read was:
"The 'class' or 'struct' constraint must come before any other constraints".
Dumb moment over.
Generics allow creating 'type variables' which can be used to create classes, functions & type aliases that don't need to explicitly define the types that they use. Generics makes it easier to write reusable code.
Assigning Generic ParametersBy passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.
TypeScript supports generic classes. The generic type parameter is specified in angle brackets after the name of the class. A generic class can have generic fields (member variables) or methods.
The TypeScript documentation explains Generics as “being able to create a component that can work over a variety of types rather than a single one.” Great! That gives us a basic idea. We are going to use Generics to create some kind of reusable component that can work for a variety of types.
... where T : class, ISessionManager
In case you want to use the where keyword
on methods here is an example that also uses generics
public void store<T>(T value, String key) { Session[key] = value; } public T retrieve<T>(String key) where T:class { return Session[key] as T ; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With