我将尝试用简单的例子来解释它。假设你还有一个类实现IPost<User>
:
class PicturePost : IPost<User>
{
// Implementation
}
那么这段代码将无法编译:
IUser<Post> user = new User();
user.Post = new PicturePost();
Because user.Post
属于具体类Post
这是不兼容的PicturePost
(他们是兄弟姐妹)。
然后想象一下您的问题中的那一行已成功编译:
// C# compiler is so kind today and it compiled this.
IUser<IPost<User>> user = new User();
Since user.Post
现在将是类型IPost<User>
你可能会编写这样的行:
IUser<IPost<User>> user = new User();
user.Post = new PicturePost();
他们将完美编译,但第二行将失败运行时错误!这是因为实际类型user.Post
is Post
not IPost
or PicturePost
.
因此,为了实现类型安全,C#编译器会在有机会编写此类代码时禁止编译。为了保证你不会写出这样的代码,Post
属性应该是只读的:
interface IUser<PostType>
{
PostType Post { get; } // No setter, this is readonly.
}
现在你将无法编写邪恶的代码,并且所有用法Post
就其接口而言将是类型安全的,因为您可以get它,然后完美地分配给其接口的变量。
但这还不够,要告诉编译器你的接口是轻量级的,你需要显式指定你的类型参数只是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();
希望我保持简单,同时没有错过要点:)