2011-05-09 14 views
5

arayüzleri kullanın jenerik ile döküm:C# Çok gibilerin intefaces uygulamak bazı jenerik arabirimleri ve sınıfları

interface A<M, N> 
     where M : X<N> 
     where N : Y 
    { 
    } 
    class B<M, N> : A<M, N> 
     where M : X<N> 
     where N : Y 
    { 

    } 

    interface X<M> where M : Y 
    { 

    } 
    interface Y 
    { 

    } 
    class X1<M> : X<M> where M : Y 
    { 

    } 
    class Y1 : Y 
    { 

    } 

Ben şeyler yapmanın çok dağınık bir yol gibi görünüyor biliyorum ama gerisini ihtiyaç başvurum için. Benim sorum ben bunu yapamam gelip nasıl:

A<X<Y>, Y> variable = new B<X1<Y1>, Y1>();

cevap

8

Marc haklıdır; Sadece bunun neden işe yaramayacağına dair biraz daha fazla bilgi vermek için.

interface IZoo<TCage, TAnimal> 
     where TCage : ICage<TAnimal> 
     where TAnimal : IAnimal 
    { 
    } 

    class Zoo<TCage, TAnimal> : IZoo<TCage, TAnimal> 
     where TCage : ICage<TAnimal> 
     where TAnimal : IAnimal 
    { 
    } 

    interface ICage<TAnimal> where TAnimal : IAnimal 
    { 
    } 

    interface IAnimal 
    { 
    } 

    class FishTank<TAnimal> : ICage<TAnimal> where TAnimal : IAnimal 
    { 
    } 

    class Fish : IAnimal 
    { 
    } 

Ve şimdi soru, neden bu yasal değildir:

Zoo<FishTank<Fish>, Fish> aquarium = new Zoo<FishTank<Fish>, Fish>(); 
IZoo<ICage<IAnimal>, IAnimal> zoo = aquarium; 

sizin aşağıdaki kod yeniden adlandırıp düşünün? varsayalım Çünkü

şimdi IZoo bir yöntem vardır:

interface IZoo<TCage, TAnimal> 
     where TCage : ICage<TAnimal> 
     where TAnimal : IAnimal 
    { 
     void PutAnimalInCage(TCage cage, TAnimal animal); 
    } 

Ve de ki:

zoo.PutAnimalInCage(giraffePaddock, giraffe); 

Ve sadece bir akvaryum içine bir zürafa padok koymak! İstediğiniz dönüşümün yasal olduğu ve IZoo'nun üzerinde seçtiğiniz herhangi bir yönteme sahip olabileceği bir dünyada tip güvenliğini sağlayamayız.

Şimdi, bu sadece tehlikeli çünkü IZoo'nun böyle bir yöntemi var. Eğer böyle bir yöntemi yoksa o zaman haklısınız, bu tamamen güvenli olabilir. C# 4.0'da, derleyiciye "bu arabirimin güvenli bir şekilde varyant olup olmadığını kontrol etmenizi", böylece "dışarı" ile eşdeğişken tür parametrelerini ekleyerek ve istediğiniz "in" ile çelişkili olmak. Bunu yaparsanız, derleyici, istediğiniz varyansın güvenilir olup olmadığını kontrol eder. Eğer yapamazsa, bu türün beyanına izin vermez.

List<Giraffe> giraffes = new List<Giraffe>(); 
List<Mammal> mammals = giraffes; // illegal 

aynı nedeni:

bu soru genelde StackOverflow'daki gelir yolu bu yasadışı neden insanlar soran olduğunu. sonra hiçbir şey sonradan

mammals.Add(new Tiger()); 

alıkoyar ve sadece zürafalar listesine bir kaplan ekledik çünkü. Aynı mantık, sadece daha basit bir dava.

8

Varyans açık olması gerekiyor (ve 4.0 C# gerektirir);

Ancak, bu aynı zamanda ... kovaryans senin arayüzü sınırlar: örneğin, bu o kovaryant olarak derlemek (arabiriminde out değiştiricileri dikkat edin) yapar! Örneğin, Add(M) yöntemine sahip olamazsınız - bu, kontavaryant olması gerektiğinden (in).

+0

hey, Bunu denediğimde, C# 4.0 dil özelliği olduğunu söylüyor ve bir hata alıyorum, ne yapmalıyım? – Twinhelix

+0

@Twinhelix - Hangi Visual Studio sürümünü kullanıyorsunuz ve hangi platform sürümünü hedefliyorsunuz? VS2010 hedefleme .NET 2.0 üzerinde benim için çalışır. C# 4.0'dan önce ... çok sınırlı durumlar için varyasyon çok azdı. –

+0

C# 4.0 gerektirir. –