2009-09-26 16 views
10

İki yöntemle MSIL küçük DLL yaptı: (MSIL sen sürece dönüş türleri farklı türde olduğu gibi aynı argümanları var yöntemleri yapmanızı sağlar biliyor olabilir bazılarınız gibiDönüş tipi aşırı yükleme kullanmak gerçekten imkansız mı?

float AddNumbers(int, int) 
int AddNumbers(int, int) 

neyi dönüş tipi aşırı yük olarak adlandırılır).

float f = ILasm1.MainClass.AddNumbers(1, 2); 

hatadır:

The call is ambiguous between the following methods or properties: 'ILasm1.MainClass.AddNumbers(int, int)' and 'ILasm1.MainClass.AddNumbers(int, int)'

farklı dönüş türleri arasında ayrım C# gerçekten aciz mi ben biraz bekliyordum olarak, C# dan kullanmaya çalıştığında Şimdi, bu bir hata ateş ? Bildiğim kadarıyla farklı dönüş türlerine sahip olan yöntemleri programlayamıyorum ama her zaman bunun nasıl ele alınacağını bildiğimi varsaydım.

+0

Seems IL bunu destekliyor http://blogs.msdn.com/abhinaba/archive/2005/10/07/478221.aspx –

+11

Bunu desteklediği için zaten biliyorum .. Yapabildiğim gibi Yukarıda yazdığım şeye bakın .. –

cevap

16

söyledi, hiçbir C# bunu desteklemiyor. Aslında, IL'nin bunu desteklemesinin nedeni, aynı tür parametreler gibi geri dönüş türleri hakkında açık olmanız gerektiğidir. Örneğin, IL size

ldarg.0 
ldarg.1 
call int AddNumbers(int, int) 

IL gerçekten yöntemi aşırı yüklenme mefhumu yoktur söyleyebilirim: float AddNumbers(int, int) kadarıyla IL söz konusu olduğunda, herhangi int AddNumbers(int, int) ilişkisi yoktur. IL derleyicisine her şeyi önceden söylemelisiniz ve asla niyetinizi (C# do gibi daha yüksek seviyeli diller gibi) denemeye çalışmaz.

Çoğu .NET dili ve C#, tür aşırı yüklemesini döndürmek için bir istisna oluşturduğuna dikkat edin: dönüşüm operatörleri.(Aksi takdirde' ve referans tipi dönüşümleri - bu ilkel (> bool böyle int gibi) türleri için desteklenmelidir böyle spesifik bir köşe durumda olduğundan Yani

public static explicit operator B(A a); 
public static explicit operator C(A a); 

public static B op_Explicit(A a); 
public static C op_Explicit(A a); 

için derlenmektedir d çok pedantik bir dil alır), bu ele alınır, ancak bir yöntem aşırı yüklenme olarak değil.

18

Evet bu gerçekten bir deyim yorumlanır yolu ile ilgisi var, ben C++ ya bu izin vermez biliyorum C# mümkün değildir:

double x = AddNumbers(1, 2); 

Burada kural atama sağ olmasıdır -kososyalleşme, yani sağdaki ifadeyi ilk önce tamamen değerlendirir ve ancak o zaman gerekli görülen durumlarda örtülü dönüşümler uygulayan ödev kabul edilir.

Derleyicinin hangi sürümün uygun olduğunu belirlemesi için bir yol yoktur. Bazı keyfi kuralı kullanmak sadece hataları bulmak için zorlu bir davettir.

Bu basit deyimi ile ilgilidir:

double y = 5/2; // y = 2.0 
+2

Çift ile güzel örnek. – RichardOD

+0

Yani aslında onlar dönüş türü kullanılarak aşırı zaman C# aramak istediğiniz yöntemi belirtmek daha yolu yoktur? – thecoop

+0

@thecoop: Hayır, bu yüzden dönüş türüne göre aşırı yüklenemezsiniz. –

4

sorun yani gerçekten amaçladığınız bilmiyor yüzer int içeren otomatik dönüştürme olmasıdır. İki inç alır ve bir int döndüren, daha sonra şamandıraya dönüştüren veya iki ints alır ve bir kayan döndüren yöntemi çağırmak niyetinde olan yöntemi çağırmak istediniz mi? Yanlış bir seçim yapmaktan ve uygulamanızı kesene kadar bildirmemenizden daha iyi bir derleyici hatası olması daha iyidir.

+0

MSIL yapabilir, lol. –

+2

@devoured no, yapamaz. MSIL, hangisini kastettiğinizi tahmin etmiyor; hangisini kastettiğinizi belirtirsiniz. C# bu durumda belirtmek için bir mekanizma yoktur. –

-3

İmleci kullanarak dönüş türünü parametre olarak aktarmaya ne dersiniz? Böyle bir şey haline gelecek çağrılması

void AddNumbers(int a, int b, float *ret){ 
    *ret = (float)(a + b); 
} 

void AddNumbers(int a, int b, int *ret){ 
    *ret = (int)(a + b); 
} 

:

int a; 
float b; 
AddNumbers(1, 2, &a); 
AddNumbers(1, 2, &b); 
+1

Evet, bu güzel bir fikir, ama gerçekten istediğim şey değil. –

+5

C# işaretçileri :) – vava

+0

olmadan bu doğrudur, fakat yukarıda da belirtildiği gibi, size ne yapmak istediğinizi yapamazsınız bunu yapabilir. Bu etraftaki bir iş. Aynı sorunu çözüyor, ama farklı bir şekilde. Bahsetmediğin başka şartlar yoksa. Varsa, onları duyalım ve bu çözümü geliştirip geliştiremeyeceğimizi göreceğiz;) – dharga

1

Hayır, bunu yapmak için hiçbir yolu yoktur. Aslında, C++ ile şablonlar dışında, hiçbir dil desteklemiyor. Bu sadece çok tehlikeli. Yine,

var a = AddNumbers(1, 1); 

ne tür a zannettiği yazarsanız?

Ya ne hangi sürümü çağırmalıdır Eğer

double a = AddNumbers(1, 1); 

hatta

AddNumbers(1, 1); 

gibi dersek?

Unutmayın, bir türün diğerine dolaylı olarak nasıl dönüştürülebileceği konusunda oldukça karmaşık kurallar vardır.double yazıp derleyici gerçekten de etmez

error C2668: 'parse' : ambiguous call to overloaded function 
could be 'float parse(float)' 

1,0 çünkü sizi buna derlemeye çalışırsanız

class Program 
{ 
    static int parse(int a) { return a; } 
    static float parse(float a) { return a; } 


    static void Main(string[] args) 
    { 
     double a = parse(1.0); 
    } 
} 

derleme değil, basit bir program bir göz atalım, derleyici size bir hata verecektir int ve float arasında ne tür bir seçim yapacağınızı bilmeniz için size bir ipucu vermenizi ister. Böylece bir işlevi çağırmadan önce devam edebilir ve bir argümanı dönüştürebilirsiniz.

Ama bu tür bir işlev geri dönüşü olsaydı, o zaman nasıl yaparsınız? Bunu yapmanın hiçbir yolu yoktur.

+0

İlk durumda, "x dönüş tipi varsayıldı" diyerek bir uyarı verecekti. İkinci durumda, float versiyonunu iade ederdi, üçüncü vaka, tıpkı ilk gibi çalışırdı. –

+0

Büyük bir nokta şudur: eğer MSIL bunu yapabilirse, neden olmasın? –

+1

MSIL'in bunu neden yaptığını hiçbir fikriniz yok. Belki de hangi işlevi istediğinizi seçebilirsiniz. Ancak uyarı sadece yanlış bir fikirle. Biraz farklı yan etkiler yapan iki fonksiyon aldığınızı düşünün. Program, işlevlerden birini kaldırana veya üçüncü bir tane ekleyene kadar iyi çalışır. Ve sonra her şey sihirli durmasına ve zaten elinde son değişikliği ile tamamen ilgisiz gibi görünüyor tüm sistemi üzerinden böcek, olurdu, çünkü ne olduğunu bulmaya kayboldu. Bu yüzden C++ tehlikeli olduğu düşünülür, bu yüzden derleyici burada karar veremediğinde hiç kimse uyarıda bulunmayacaktır. – vava

2

Her iki yöntemi de aynı derlemede tutabilen MSIL, hangisinin çağrılacağını belirleyen derleyici ile ilgisi yoktur.

Kovaryant dönüş türleri uzun yıllardır tartışılmış, Java'ya kısmen izin verilmiş, C++ özel bir durum vardır ve C# tasarımcıları added some minor changes to 4.0 sahiptir.

Oyuncak probleminiz için basit tipik çözümler vardır. Örneğin, float AddNumbers(int, int)'nuz muhtemelen her zaman (float) AddNumbers(int, int) ile aynı olacaktır, bu durumda ikinci işleve gerek yoktur. Tipik olarak bu durum jeneriklerle işlenir: <T> AddNumbers(<T> n1, <T> n2), böylece float AddNumbers(float, float) ve int AddNumbers(int, int) ile sonuçlanırsınız.

Gerçek yaşam senaryosunun, dönmek istediğiniz farklı gösterimleriniz olduğu yerde olma olasılığı daha yüksektir, ancak yöntemi yeniden adlandırmak istemezsiniz. Miras/geçersiz kılma kullanım durumunda, bu somewhat with generics'u da çözebilirsiniz.

İstediğiniz gibi yapmak istediğim birkaç durumda, yöntemleri uzun vadede daha okunabilir ve sürdürülebildiğinden daha uygun şekilde adlandırmak daha iyi bir hale geldi.

Bu, zaten here da tartışılmıştır.

http://blogs.msdn.com/abhinaba/archive/2005/10/07/478221.aspx numaralı telefondan MSIL/C# içindeki durum, özellikle açık dönüşüm operatörleri oldukları için özeldir.

+0

Kimse bunu söylemedi. –

+0

Bağlantılı sayfanın hangi bitinin "gelebileceğini" belirtebilir misiniz? –

+0

Yalnızca 4.0 değişikliğinden bahsetmek için düzeltilmiş bir ifade. –

21

ECMA-334 C# Bölüm 8.7.3

The signature of a method consists of the name of the method and the number, modifiers, and types of its formal parameters. The signature of a method does not include the return type.

Sen genel bir yöntem kullanabilirsiniz: Herkes gibi

T AddNumbers<T>(int a, int b) 
{ 
    if (typeof(T) == typeof(int) || typeof(T) == typeof(float)) 
    { 
     return (T)Convert.ChangeType(a + b, typeof(T)); 
    } 

    throw new NotSupportedException(); 
} 
+1

Genel bir yöntemin kullanılması, bunu yapmanın iyi bir yoludur. – acarlon