2013-03-26 33 views
8

Projemizde sahip olduğumuz bir sorunla karıştırıldım. Ben etkiyi çoğaltmak için basitleştirmek için çalıştı:C# Yöntem aşırı yükleme ve genel arayüz

interface IBar { } 

class Bar : IBar {} 

interface IFoo<T> where T : IBar { } 

class Foo<T> : IFoo<T> where T : IBar { } 


class Class1 
{ 
    public void DoTheFoo<T>(T bar) where T : IBar 
    {} 

    public void DoTheFoo<T>(IFoo<T> foo) where T : IBar 
    {} 


    public void Test() 
    { 
     var bar = new Bar(); 
     var foo = new Foo<Bar>(); 

     DoTheFoo(bar); // works 

     DoTheFoo<Bar>(foo); // works 
     DoTheFoo((IFoo<Bar>)foo); // works 
     DoTheFoo(foo); // complains 
    } 
} 

bu iyi görünüyor Bana göre, ancak DoTheFoo<T>(IFoo<T> foo) yerine, DoTheFoo<T>(T bar) çalışır ve argüman türü uymuyor şikayet çünkü derleyici, son çağrı şikayet .

  • DoTheFoo<T>(T bar) yöntemini kaldırdığımda, son çağrı çalışıyor!
  • Ben DoTheFoo<T>(Foo<T> foo) olarak değiştirin, bu çalışıyor, ama bizim şimdiki kodunda bu geçici bir çözüm için çok zor değil

olduğunu kullanamaz. Ama a) tuhaf ve b) çok fazla kötü olan bu iki aşırı metoda sahip olamayız.

Bu davranışı açıklayan ortak bir kural var mı? Çalışmasını sağlamak mümkün mü (yöntemleri farklı isimler vermek dışında)?

+0

Bunun bir kopya olduğunu sanmıyorum. Genel kısıtlamalarda yöntemlerin farklı olması sorunu vardır. Yöntemler, bildirilen bağımsız değişken türünde farklıdır. –

+0

Hayır, bu bir kopya. Cevabımı dikkatlice oku. Aşırı yük çözünürlüğünün sizin durumunuzda neden yöntemi seçtiğini açıklar. –

cevap

7

Bu, sadece aşırı yüklenme çözünürlüğü ile birleştirildiğinde sizin lehinize çalışmayan bir tür çıkarsama meselesidir. Sadece açıkça tip argüman belirterek halletmek kolay - hayır döküm gereklidir:

DoTheFoo<Bar>(foo); 

Genellikle olsa oldukça farklı parametre türleri dikkate alınır aşırı sinir değilim. Çoğu kez yöntemleri farklı isimler verirseniz, kod daha basit bir şekilde biter. Kenara Her şey bir yana, sonra okuyucular ... tür kesmesi ile aynı anda aşırı yük çözünürlüğü gerçekleştirmek için denemek için

DÜZENLEMEYİ gerekmez: Ben sorunun sipariş böyle çalıştığını olduğuna inanıyorum:

böylece ilk yöntem için, biz T = Foo<Bar> olsun ve ikinci yöntem için biz T = Bar olsun -
  • Her iki yöntem
  • Tipi çıkarım kısıtlamaları doğrulayarak olmadan iki yöntemde uygulanır bulunur. Her iki yöntem de bu noktada uygulanabilir.
  • Aşırı yükleme çözünürlüğü gerçekleştirilir; bu, ilk yöntemin en belirgin olanı olduğuna karar verir. aşırı yük çözünürlük yapılmıştır Sadece sonra
  • kontrol T üzerinde kısıtlama - ve Bar den IFoo hiçbir referans dönüşüm var, çünkü o başarısız olur.

bir Eric Lippert blog post about why the language is designed this way, bir blog post I wrote about it ve an article I wrote about overloading in general var. Her biri veya yardımcı olmayabilir :)

DÜZENLEME: Bir an için bir kenara yazın çıkarım bırakarak, ilk yöntem daha spesifik olmasının nedeni bir durumda biz Foo<Bar> için Foo<Bar> dönüştürme, diğerinde olduğunuzdur Foo<Bar>'dan IFoo<Bar>'a dönüştürüyoruz. Bölüm 7.5.3'e göre.Bir tür T1 bir ekspresyon E dönüştüren bir kapalı dönüştürme C1 ve bir tür T2 bir ekspresyon E dönüştüren bir kapalı dönüştürme C2 göz önüne alındığında

, C1-daha iyi bir dönüşüm: C 5. tarifnamenin 3

kimlik dönüşüm dan ... - E türü S sahip olan ve bir kimlik dönüşüm S'den T1 ancak S T2 için vardır - : C2 den aşağıdakilerden en az biri dayanırsa 'un olduğu ilk aşırı yük durumunda, f ya da ikinci. Yani ilk dönüşüm daha iyidir.

+1

Bunun tür çıkarımından kaynaklandığından emin değilim. Türün argümanlar tarafından söylenemeyeceğinden şikayet etmediğini düşünün. Aynı zamanda, ilk DoTheFoo yöntemi kaldırıldığında da çalışır ... –

+1

@StefanSteinegger: Aşırı yükleme * ile sonuç çıkarımı başarısız oluyor *. Her şey gerçekten zor - şartname tüm onu ​​takip etmeyi deneyin - ama açıkça tür çıkarımı sorunun * parçası *, aksi takdirde kesinlikle tür argümanını belirttiğinizde işe yaramaz. –

+0

Aslında bu davanın en garip kısmı. Genel argümanı belirttiğimde işe yarıyor. En azından ilk aşırı yük kaldırıldığında, onu bulma yeteneğine sahip olsa da. –

İlgili konular