postaram się wyjaśnić za pomocą prostego przykładu. Załóżmy, że masz jeszcze jedną klasę wykonawczą IPost<User>
:
class PicturePost : IPost<User>
{
// Implementation
}
Wtedy ten kod nie zostanie skompilowany:
IUser<Post> user = new User();
user.Post = new PicturePost();
Ponieważ user.Post
jest z betonu klasy Post
, który nie jest kompatybilny z PicturePost
(są rodzeństwem).
Następnie wyobraź sobie, że linia z pytaniem został pomyślnie skompilowany:
// C# compiler is so kind today and it compiled this.
IUser<IPost<User>> user = new User();
Od user.Post
teraz będzie od rodzaju IPost<User>
potencjalnie będą kodować takie linie:
IUser<IPost<User>> user = new User();
user.Post = new PicturePost();
I będą doskonale kompilacji ale druga linia nie powiedzie się z błędem czasu wykonania! Dzieje się tak, ponieważ rzeczywisty typ user.Post
to Post
, a nie IPost
lub PicturePost
.
Tak więc, aby osiągnąć bezpieczeństwo typu, kompilator C# zabrania kompilacji, jeśli istnieje szansa, że taki kod zostanie zapisany. W celu zapewnienia, że nie będzie napisać taki kod, Post
nieruchomość powinna być tylko do odczytu:
interface IUser<PostType>
{
PostType Post { get; } // No setter, this is readonly.
}
Teraz nie będzie w stanie napisać zły kod i wszystkie zwyczaje Post
będzie typu bezpieczny w odniesieniu jego interfejsu, ponieważ można po prostu uzyskać go, a następnie idealnie przypisać do zmiennej jego interfejsu.
Ale to nie wystarczy, aby powiedzieć kompilatorowi, że twój interfejs po jasnej stronie, musisz wyraźnie określić, że twój parametr typu jest tylko poza (możesz go użyć, ale nie możesz go przekazać). Tak więc, mając poniżej realizacji interfejsu (zauważ out
słowa kluczowego), Twój kod zostanie skompilowany:
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();
nadzieja Ciągle jest prosta i nie przegap punkt w tym samym czasie :)
Możesz zacząć [tutaj ] (http://blogs.msdn.com/b/ericlippert/archive/2007/10/26/covariance-and-contravariance-in-c-part-five-interface-variance.aspx) –