提前谢谢你。这是我的代码:
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
}
}
public class AppUserManager : UserManager<ApplicationUser>
{
...
}
public interface IOwinManager
{
UserManager<IdentityUser> UserManager { get; }
}
为什么这不起作用?
public class OwinManager : IOwinManager
{
public UserManager<IdentityUser> UserManager
{
get { return new AppUserManager(); }
}
}
由于ApplicationUser从UserManager继承IdentityUser和AppUserManager,为什么组合泛型不被接受?谢谢!
答案 0 :(得分:4)
不支持类的泛型类型参数的逆变和协方差。
简化您的问题:
// Compiler error!
UserManager<IdentityUser> userManager = new AppUserManager();
AppUserManager
继承UserManager<ApplicationUser>
。UserManager<ApplicationUser>
引用上设置UserManager<IdentityUser>
派生的引用。这就是问题!他们是不同的类型。OP说...... :
这基本上意味着我不能使用具体的课程和他们的 界面中的泛型并期望它们由它们实现 儿?
接口支持差异。因此,您可以按如下方式设计界面:
public interface IOwinManager<out TUser, out TManager>
where TUser : IdentityUser
where TManager : UserManager<TUser>
{
TManager UserManager { get; }
}
...一旦您实现了此接口,您的实现将声明具体TManager
类型的属性。
答案 1 :(得分:3)
马蒂亚斯的回答很好;我以为我会添加更多的上下文。让我们再次简化您的示例:
class Animal {} // IdentityUser
class Tiger : Animal {} // ApplicationUser
class Giraffe : Animal {} // some other kind of user
class Cage<T> where T : Animal {} // UserManager
class SpecialTigerCage : Cage<Tiger> {} // AppUserManager
现在的问题是&#34;为什么这种转换是非法的?&#34;
Cage<Animal> cage = new SpecialTigerCage();
现在应该很清楚为什么这是非法的。 你可以将长颈鹿放入可以容纳动物的笼子里,但是如果你把长颈鹿放进一个特殊的虎笼里,长颈鹿就不会对此感到高兴。
类型系统无法证明您不会将长颈鹿放入该虎笼,因此不允许转换。
正如其他人所指出的那样,C#支持在接口和代理上进行这种协变转换,可以证明你不会将长颈鹿放入虎笼。例如IEnumerable<T>
是协变的。在需要一系列动物的情况下,可以使用一系列老虎,因为IEnumerable<T>
可证明没有方法可以将长颈鹿插入序列中。