5

我不确定这里发生了什么,但使用以下代码出现编译器错误:

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

Post如果是 的子类型,为什么我会收到错误消息IPost<User>?我知道在这种情况下我可以只使用User而不是IUser<IPost<User>>,但我想知道为什么这不起作用。

4

2 回答 2

12

我将尝试用简单的例子来解释它。假设您还有一个类实现IPost<User>

class PicturePost : IPost<User>
{
    // Implementation
}

那么这段代码将无法编译:

    IUser<Post> user = new User();
    user.Post = new PicturePost();

因为是不兼容user.Post的具体类(它们是兄弟姐妹)。PostPicturePost

然后想象您问题中的那一行已成功编译:

    // C# compiler is so kind today and it compiled this.
    IUser<IPost<User>> user = new User();

由于user.Postnow 将是类型IPost<User>,您可能会编写这样的代码行:

    IUser<IPost<User>> user = new User();
    user.Post = new PicturePost();

他们将完美编译,但第二行将因运行时错误而失败!这是因为实际类型user.Post不是or 。PostIPostPicturePost

因此,为了实现类型安全,如果有可能编写此类代码,C# 编译器将禁止编译。为了确保您不会编写此类代码,Post属性应该是只读的:

interface IUser<PostType>
{
    PostType Post { get; } // No setter, this is readonly.
}

现在您将无法编写邪恶的代码,并且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();

希望我保持简单,同时不要错过重点:)

于 2013-03-24T08:07:04.620 回答
0

那么你必须让你的接口协变:

interface IUser<out PostType>
{
    PostType Post { get; }
}

interface IPost<out UserType>
{
    UserType User { get;  }
}

请参阅 http://msdn.microsoft.com/en-gb/library/ee207183.aspx http://msdn.microsoft.com/en-gb/library/dd799517.aspx

于 2013-03-24T08:06:11.827 回答