C#泛型接口协方差
我不确定这里发生了什么,但使用以下代码得到了一个编译器错误:C#泛型接口协方差,c#,generics,covariance,C#,Generics,Covariance,我不确定这里发生了什么,但使用以下代码得到了一个编译器错误: namespace SO { interface IUser<PostType> { PostType Post { get; set; } } interface IPost<UserType> { UserType User { get; set; } } class User : IUser<Post>
namespace SO
{
interface IUser<PostType>
{
PostType Post { get; set; }
}
interface IPost<UserType>
{
UserType User { get; set; }
}
class User : IUser<Post>
{
//Implementation
}
class Post : IPost<User>
{
//Implementation
}
class SomeOtherClass
{
// Compiler Error: Cannot implicitly convert type 'SO.User' to
// 'SO.IUser<SO.IPost<SO.User>>'. An explicit conversion exists
// (are you missing a cast?)
IUser<IPost<User>> user = new User();
//Works Fine
IUser<Post> user = new User();
}
}
SO
{
接口IUser
{
PostType Post{get;set;}
}
接口IPost
{
用户类型用户{get;set;}
}
类用户:IUser
{
//实施
}
班级职务:IPost
{
//实施
}
给别人上课
{
//编译器错误:无法将类型“SO.User”隐式转换为
//“SO.IUser”。存在显式转换
//(你错过了演员阵容吗?)
IUser user=新用户();
//很好
IUser user=新用户();
}
}
如果
Post
是IPost
的子类型,为什么会出现错误?我知道在这种情况下,我可以使用User
而不是IUser
,但我想知道为什么这不起作用。好吧,你必须让你的界面变得不同:
interface IUser<out PostType>
{
PostType Post { get; }
}
interface IPost<out UserType>
{
UserType User { get; }
}
接口IUser
{
PostType Post{get;}
}
接口IPost
{
用户类型用户{get;}
}
看
我将尝试用简单的例子来解释它。假设您还有一个类实现了
IPost
:
由于user.Post
现在将是IPost
类型,因此您可能会对以下行进行编码:
IUser<IPost<User>> user = new User();
user.Post = new PicturePost();
现在,您将无法编写邪恶的代码,Post
的所有用法在其接口方面都是类型安全的,因为您只需获取它,然后再完美地分配给它接口的变量
但这还不够,要告诉编译器您的接口是轻量级的,您需要显式地指定您的类型参数仅为out(您可以使用它,但不能将它传递到)。因此,有了以下接口实现(注意out
关键字),您的代码将编译:
interface IUser<out PostType>
{
PostType Post { get; } // No setter, this is readonly.
}
// Both lines compile!
IUser<IPost<User>> user = new User();
IUser<Post> user1 = new User();
接口IUser
{
PostType Post{get;}//没有setter,这是只读的。
}
//两行都编译!
IUser user=新用户();
IUser user1=新用户();
希望我保持简单,同时不要错过要点:)你可以开始了
// C# compiler is so kind today and it compiled this.
IUser<IPost<User>> user = new User();
IUser<IPost<User>> user = new User();
user.Post = new PicturePost();
interface IUser<PostType>
{
PostType Post { get; } // No setter, this is readonly.
}
interface IUser<out PostType>
{
PostType Post { get; } // No setter, this is readonly.
}
// Both lines compile!
IUser<IPost<User>> user = new User();
IUser<Post> user1 = new User();