带有约束的模板化成员变量,无法强制转换,为什么?

Templated member variable with constraints, cannot cast, why?

提问人:ActiveX 提问时间:4/21/2022 最后编辑:ActiveX 更新时间:4/21/2022 访问量:27

问:

我有以下类定义:

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

那为什么我不能做这个演员表:

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

这是编译器消息: 无法将类型“xxx.Persistence.IStatefulSession”隐式转换为“TSession”。存在显式转换(是否缺少强制转换?

但我可以这样做:

_session = (TSession)HibernateContext.Current.AcquireNewSession();
C# .NET 泛型转换

评论

2赞 dbc 4/21/2022
你没有展示一个完整的最小可重复的例子,所以我在这里猜测一点。 是一个,但它可能更多,它可能是某个实现许多附加接口并具有许多不相关成员的类。因此,如果仅返回某种类型,那么我们不知道它可以分配给 .我们所知道的是,类型的东西可以分配给类型的东西。TSessionIStatefulSessionHibernateContext.Current.AcquireNewSession()IStatefulSessionTSessionTSessionIStatefulSession
0赞 ActiveX 4/21/2022
有道理,谢谢。

答:

1赞 Morten Ankerstjerne 4/21/2022 #1

有关更多信息,请查看 https://learn.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance

短版本基本上是返回一个接口,它不如实现该接口的类具体。AcquireNewSessionIStatefulSessionTSession

您必须将不太具体的类型显式转换为更具体的类型,这是可能的,因为给定的约束。

然而,反其道而行之总是可以的,因为我们总是可以将更具体的类型分配给不太具体的类型。

这基本上与你总是可以为变量赋值的原因相同,但如果你想将它赋值给变量,你必须显式地强制转换。stringobjectobjectstring