SORU
5 EKİM 2011, ÇARŞAMBA


Neden yok C# "türlerini birleştirmek" olabilir; farklı temel sınıflardan elde ne zaman?derleyici şikayet

Non-derleme benim geçerli kod şuna benzer:

public abstract class A { }

public class B { }

public class C : A { }

public interface IFoo<T>
{
    void Handle(T item);
}

public class MyFoo<TA> : IFoo<TA>, IFoo<B>
    where TA : A
{
    public void Handle(TA a) { }
    public void Handle(B b) { }
}

C# derleyicisi bu derlemeye, aşağıdaki kural/hata gerekçe göstererek reddetti:

'MyProject.MyFoo<TA>' uygulamak 'MyProject.İFoo<TA>' ve 'MyProject.İFoo<MyProject.B>' çünkü onlar tipinde parametre oyuncu değişikliği birleştirmek olabilir

Bu hata ne anlama geldiğini anlıyorum; eğer TA herhangi bir şey olabilir eğer teknik olarak da Handle iki farklı uygulamalar konusunda belirsizlik tanıtmak hangi B olabilir.

Ama TAolamazherhangi bir şey olabilir. Türü hiyerarşisi, TA dayanarakolamazB - en azından, bilmiyorumdüşünüyorumolabilir. TA yok A, türetilmesi gerekirdeğilbirden fazla C sınıfı miras yok açıkçası B ve türevi#/.NET.

Ben genel parametre kaldırın ve C hatta A TA değiştir, derler.

Neden bu hatayı alıyorum? Ya da genel istihbarat BM derleyici, yoksa kaçırdığım başka bir şey mi bir hata var?

Herhangi bir geçici çözüm veya sadece TA türetilmiş her tür için genel olmayan ayrı bir sınıf olarak yeniden hayata MyFoo genel sınıf olacak mıyım?

CEVAP
5 EKİM 2011, ÇARŞAMBA


Bu 13.4.2 C Birleşik Devletleri:# 4 belirtimi, bölüm bir sonucudur

Eğer herhangi bir olası inşa edilen C tipi oluşturulan bir tür bağımsız değişkenleri L terk ettikten sonra, ben iki arabirim aynı olması neden olursa, o zaman C ilanının geçersiz. Kısıtlama tanımlamalar Olası inşa edilen her türlü belirlenmesinde dikkate alınmaz.

İkinci cümle yok edin.

Bu nedenle derleyici bir hata değil; derleyici doğru. Bir dil belirtimi bir kusur olduğunu iddia edebilir.

Genel olarak konuşursak, kısıtlamaları olan bir gerçek genel bir tür hakkında bir çıkarım olmalı her durumda göz ardı edilir. Kısıtlamaları çoğunlukla belirlemek için kullanılıretkili temel sınıfgenel tür parametre, ve biraz başka.

Ne yazık ki, bazen dilini keşfettim gibi gereksiz yere sıkı olduğu bir duruma yol açar.


Genel olarak "arayüzü iki kez, bir şekilde genel tür bağımsız değişkenleri yalnızca ayırt." aynı uygulamaya kötü kod kokusunu Örneğin, kaplumbağalar bir dizi de, o C nedir class C : IEnumerable<Turtle>, IEnumerable<Giraffe> -- olması tuhafvezürafalar bir diziaynı zamanda? Burada yapmaya çalıştığın gerçek şeyi tarif EDEBİLİR MİSİN? Gerçek sorunu çözmek için iyi bir model olabilir.


Aslında eğer arayüzü tam olarak tarif ettiğiniz gibi

interface IFoo<T>
{
    void Handle(T t);
}

Sonra arayüz çoklu kalıtım bir sorun çıkarıyor. Doğal olarak bu arayüzü karşıtı yapmak için karar verebilirsiniz:

interface IFoo<in T>
{
    void Handle(T t);
}

Şimdi varsayalım

interface IABC {}
interface IDEF {}
interface IABCDEF : IABC, IDEF {}

Ve

class Danger : IFoo<IABC>, IFoo<IDEF>
{
    void IFoo<IABC>.Handle(IABC x) {}
    void IFoo<IDEF>.Handle(IDEF x) {}
}

Ve şimdi her şey iyice çığırından...

IFoo<IABCDEF> crazy = new Danger();
crazy.Handle(null);

Kolu uygulama çağrılır???

Bu makale ve bu konuda daha fazla düşünce için bkz: açıklamalar:

http://blogs.msdn.com/b/ericlippert/archive/2007/11/09/covariance-and-contravariance-in-c-part-ten-dealing-with-ambiguity.aspx

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Bobbylee Budde

    Bobbylee Bud

    13 ŞUBAT 2011
  • RinconDynamic

    RinconDynami

    1 EKİM 2011
  • TVNorge

    TVNorge

    5 EKİM 2006