2012-02-20 22 views
13

GÜNCELLEME: Aşağıdaki kodu yalnızca ben kovaryans bazı yanlış anlama yaşıyorum gibi görünüyor C# 4.0 (Visual Studio 2010)Kovaryans/contravariance: Aşağıdaki kodu nasıl derlemek

yılında anlamda yapar/contravariance şey . Aşağıdaki kodun neden derlenmediğini söyleyen var mı?

public class TestOne<TBase> 
{ 
    public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values) 
     where TDerived: TBase 
    { 
     return values; 
    } 
} 

bu derler ederken: (!!!) bir sınıf kısıtlaması ekleme zorunda

public interface IBase 
{ 
} 
public interface IDerived: IBase 
{ 
} 
public class TestTwo 
{ 
    public IEnumerable<IBase> Method(IEnumerable<IDerived> values) 
    { 
     return values; 
    } 
} 

cevap

13

Kovaryans yalnızca (tip argümanlar için) türlerini başvurmak için geçerlidir:

public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values) 
    where TDerived : class, TBase 
{ 
    return values; 
} 

Bu, bir IEnumerable<int> numarasını IEnumerable<object> içine dönüştürmeyi denemenizi engelleyecektir, bu geçersizdir.

+0

@Adam: Ben yanlış olduğuna inanıyoruz, 'hatta içinde' 3.5' ​​ – sll

+1

@AdamMihalcin derlemek olmaz bu yüzden varsayılan olarak '' IEnumerable IEnumerable değil ': Hayır, bu kodu * olmaz * .NET 4.'den derledim. Bunu doğrulamak için kendim denedim. Genel değişmezlik olmadan, IEnumerable 'ile IEnumerable ' arasındaki dönüşüm geçersizdir. –

+0

TSuper ile ilgili iyi bir çağrı, sadece –

1

Gerçekten TDerived'a gereksinim duyduğunuz herhangi bir durumu düşünemiyorum. TBase kullanılması yeterlidir: Sonuçta

public class TestOne<TBase> 
{ 
    public IEnumerable<TBase> Method(IEnumerable<TBase> values) 
    { 
     return values; 
    } 
} 

, yaklaşık TDerived gerçeği dışında bir TBase olduğuna bilgimiz yok ...

+2

maalesef bu karmaşıklık uğruna yaptığım bir şey değil, sahip olduğum gerçek bir durum Benim kodumda –

+1

@bonomo: Bu ilginç, gelecekteki referans için daha ayrıntılı bir örnek görmek isterim. :-) – linepogl

0

Ne başlangıçta benim için derlenmiş. Her ikisi de Super (T/I) 'dan Base (T/I)' a kadarki örtülü dökümde başarısız oldu. Ancak, açık bir vaka eklediğimde, her ikisi de derlenmişti.

public IEnumerable<TBase> Method<TSuper>(IEnumerable<TSuper> values) 
    where TSuper: TBase 
    { 
     return (IEnumerable<TBase>) values; 
    } 
İlgili konular