Home > Software design >  Templated member variable with constraints, cannot cast, why?
Templated member variable with constraints, cannot cast, why?

Time:04-22

All,

I have the following class definition:

public class SessionScope<TSession> : ISessionScope<TSession>
        where TSession : class, IStatefulSession
    {
        private TSession _session; // Constraint as IStatefulSession
    }

Then why I cannot do this cast:

_session = HibernateContext.Current.AcquireNewSession(); // AcquireNewSession() returns IStatefulSession

This is the compiler message: Cannot implicitly convert type 'xxx.Persistence.IStatefulSession' to 'TSession'. An explicit conversion exists (are you missing a cast?)

But I can do this:

_session = (TSession)HibernateContext.Current.AcquireNewSession();

CodePudding user response:

For more information, check out https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance

The short version is basically that AcquireNewSession returns an interface IStatefulSession, which is less specific than TSession, a class implementing that interface.

You have to explicitly cast the less specific type to the more specific type, which is possible because of the given constraint.

Going the other way, however, is always fine, because we can always assign the more specific type to a less specific type.

It's basically the same reason you can always assign a string to an object variable, but you have to explicitly cast an object if you want to assign it to a string variable.

  • Related