views:

273

answers:

3

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.

+9  A: 
... where T : class, ISessionManager
Mehrdad Afshari
Ar**. I've been writing where T : ISessionManager, class!
GenericTypeTea
That'll teach me to read compiler errors properly.
GenericTypeTea
+6  A: 
where T : class, ISessionManager

you can go even further

where T : class, ISessionManager, new()

this will force non abstract class with parameterless ctor to be handed in as T

Andreas Niedermair
+1 for coming second.
GenericTypeTea
+1 for adding new()
Stevo3000
+1  A: 

Read up on Constraints on Type Parameters in C#.

In this particular case, you must ensure that T is a class:

public abstract class SessionManager<T>
    where T : class, ISessionManager
DrJokepu
That won't build. ;) class has to come first. Plus, all of the constraints for a particular type must be specified in a single where clause...
GenericTypeTea
You're right, I forgot the syntax, fixed.
DrJokepu
+1 for updating.
GenericTypeTea