Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#泛型接口协方差_C#_Generics_Covariance - Fatal编程技术网

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();