2011-12-06 26 views
8

Bu konuda biraz yardıma/yardıma ihtiyacım var, ağaçları artık ağaçlardan göremiyorum.C# Döküm jenerikleri (kovaryans ve kontravaryans?)

Bu, jenerik kullanarak bazı arabirimleri uygulayan düz ileri bir dizi sınıftır.

Sonra örneğin beton tiplerinin dökülmesi çalışıyorum:

MyGenericObject<SomeObject> _obj; 

IMyGenericObject<ISomeObject> _genObj = (IMyGenericObject<ISomeObject>)_obj; 

// Geçersiz ben Kovaryans ve contravariance ama çok net değil ilgili bazı makaleler okudum

dökme neden bu wouldn' Mümkün mü, yoksa nasıl dönülür?


Yani, bu örnekte: Alacağınız ve Etkinlik özelliğini ayarlayın olamaz, çünkü

public interface IMyObject<in T> where T : IBaseObject 
{ 
    T Activity { get; set; } 
} 

.... ...


işe yaramaz . Bu örnekte

, Yapmam gereken: Yardım için herkese birisi ve teşekkür yardımcı olur

public interface IMyObject<out T> where T : IBaseObject 
    { 
     T Activity { get; } 
    } 

umut!

+0

Arayüzü tanımınızı gösterir. –

cevap

9

Yalnızca, arabirimi bir kovaryant (out) parametresi olarak bildirirseniz bunu yapabilirsiniz. Sadece eğer parametre kovaryant olarak kullanılıyorsa bunu yapabilirsiniz. Örneğin, IMyGenericObject<T> arabiriminin T parametresini kullanan bir yöntemi varsa, bu, parametrenin kovaryant olarak bildirilmesini engeller. Tersine, bir T döndüren bir yöntem varsa, bu, parametreyi contravariant olarak bildirmenizi engeller. SLaks cevabı hakkındaki yorumunuzu yanıt olarak

DÜZENLEME

, herşeyi Eric Lippert'ın hiç ko- ve contravariance üzerinde yazmıştır tekrarlamak için cazip. Bir FileInfo bir IList<object> geçmek yasal çünkü

Sen IList<object> için IList<string> döküm olamaz, ama Geçmesi yasal değildir: (en son https://stackoverflow.com/a/8380213/385844) SO içinde http://blogs.msdn.com/b/ericlippert/archive/tags/Covariance+and+Contravariance/ ve aynı zamanda onun cevaplarını göster

Özetlemek gerekirse IList<string>'a.

bir IList<string> bir eleman almak ve bir dize referansı atamak için yasal, çünkü bir IList<string> bir IList<object> döküm olamaz, ama bir IList<object> bir dizeye atanamaz bir FileInfo, içerebilir referans.

DÜZENLEME 2

Eğer tavsiye istedi yana, ko- ve kontravaryant bölüme Arabirimlerinizden bölmek de mümkündür. Liste örnekle devam edebilmek Bu bağlama göre, covariantly veya contravariantly sınıfı kullanmasını sağlar bu arayüzleri

public interface ICovariantList<out T> 
{ 
    T this[int index] { get; } 
    //... 
} 

public interface IContravariantList<in T> 
{ 
    T this[int index] { set; } 
    void Add(T item); 
    //... 
} 

public class SomeList<T> : ICovariantList<T>, IContravariantList<T> 
{ 
    //... 
} 

olabilir.

+0

sıralanan bu upvotes almak gerektiğini herhangi bir neden göremiyor, yardım için teşekkürler! – sambomartin

+0

@sambomartin hoşgeldiniz. EDIT 2'de daha fazla öneri var. – phoog

+0

Teşekkürler, her ne kadar nihayetinde dizgiye ihtiyacım olmasa da ... ... bir dahaki sefere işittim ... ama bir dahaki sefere biliyorum! – sambomartin

4

Arabirimi, bir kovaryant (out) genel parametresi olarak bildirmeniz gerekir.

+2

covariant is 'out'; contravariant 'in' dir. Mnemonic: kovaryant ve dışarı için “o”; contravariant için "n" ve " – phoog

+0

tamam, teşekkürler. Bir sonraki sorun, derleyicinin rapor ettiği: "Hata 1 Geçersiz varyans: 'xxx tip parametresi' xxx 'de değişmez olmalıdır. Okuduğum şeyden, arayüzün sadece/değişmez okumasını sağlamalıyım. IMyGenericInterface SomeObject SomeObjectInstance {get; set;} Herhangi bir fikri var mı? – sambomartin

+0

@sambomartin: Varyansın nasıl çalıştığını anlamanız gerekir. Yazılabilir bir varyant özelliği, doğal olarak güvenli olmayan türden bir özelliktir. – SLaks