2009-09-26 14 views
10

मैं दो तरीकों के साथ MSIL में एक छोटा सा DLL बनाया:रिटर्न प्रकार ओवरलोडिंग का उपयोग करना वास्तव में असंभव है?

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

आप में से कुछ पता होगा, MSIL आप जब तक आप बदले प्रकार के विभिन्न प्रकार है जैसे तरीकों है कि एक ही तर्क बनाने के लिए अनुमति देता है (क्या रिटर्न टाइप ओवरलोडिंग कहा जाता है)।

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

त्रुटि है:

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

सी # वास्तव में अलग वापसी प्रकार के बीच भेद करने में असमर्थ है अब, जब मैं ग # से इसका इस्तेमाल करने, के रूप में मैं थोड़े उम्मीद कर रहा था की कोशिश की, यह एक त्रुटि निकाल दिया ? मुझे पता है कि मैं उन प्रोग्राम विधियों को नहीं कर सकता जो कि अलग-अलग रिटर्न प्रकारों के अंतर के रूप में हैं, लेकिन मैं हमेशा मानता हूं कि यह इसे संभालने का तरीका होगा।

+0

लगता है कि आईएल इसका समर्थन करता है http://blogs.msdn.com/abhinaba/archive/2005/10/07/478221.aspx –

+11

यह इसका समर्थन करता है मुझे पहले से ही पता है..मैंने इसके साथ एक असेंबली बनाई है, जैसा कि आप कर सकते हैं मैंने जो लिखा है उसमें देखें .. –

उत्तर

16

हर किसी की तरह कहा है, कोई सी # इस समर्थन नहीं करता। असल में, कारण आईएल इसका समर्थन करता है, क्योंकि आपको पैरामीटर की तरह रिटर्न प्रकारों के बारे में स्पष्ट होना चाहिए। उदाहरण के लिए, आईएल में आप कहेंगे

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

आईएल वास्तव में विधि ओवरलोडिंग की एक धारणा नहीं है: float AddNumbers(int, int), जो भी int AddNumbers(int, int) से कोई संबंध नहीं जहाँ तक आईएल संबंध है। आप पहले से आईएल संकलक सब कुछ बताने के लिए है, और इसे आप अनुमान लगाने के लिए कोशिश करता है कभी नहीं आशय (जैसे सी # उच्च स्तर भाषाओं कर की तरह)।

नोट है कि ज्यादातर नेट भाषाओं और सी # प्रकार ओवरलोडिंग वापस जाने के लिए एक अपवाद बनाने: रूपांतरण ऑपरेटरों।तो

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); 

करने के लिए संकलित किया गया है क्योंकि इस तरह के एक विशिष्ट कोने मामले (जैसे पूर्णांक के रूप में -> bool) आदिम प्रकार के लिए समर्थित किया जाना है और संदर्भ प्रकार रूपांतरण (आप अन्यथा ' डी बहुत ही पैडेंटिक भाषा प्राप्त करें), इसे संभाला जाता है, लेकिन विधि अधिभार के मामले में नहीं।

18

हाँ, यह वास्तव में संभव नहीं सी # में, मैं जानता हूँ कि सी ++ या तो इस की अनुमति नहीं है, यह रास्ता एक बयान व्याख्या की है के साथ क्या करना है:

double x = AddNumbers(1, 2); 

नियम है कि यहाँ काम सही है - सहयोगी, जिसका मतलब है कि दाईं तरफ अभिव्यक्ति पूरी तरह से मूल्यांकन की जाती है और केवल तभी असाइनमेंट माना जाता है, जहां जरूरी रूपांतरण लागू होते हैं।

संकलक यह निर्धारित करने के लिए कोई तरीका नहीं है कि कौन सा संस्करण सबसे उपयुक्त है। कुछ मनमानी नियमों का उपयोग करना त्रुटियों को खोजने के लिए कड़ी मेहनत करेगा।

यह इस सरल बयान से संबंधित है:

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

डबल के साथ अच्छा उदाहरण। – RichardOD

+0

तो वास्तव में कोई तरीका नहीं है कि आप किस विधि को सी # में कॉल करना चाहते हैं, जब वे रिटर्न प्रकार का उपयोग करके अधिभारित होते हैं? – thecoop

+0

@thecoop: नहीं, और यही कारण है कि आप रिटर्न प्रकार से अधिभार नहीं कर सकते हैं। –

4

समस्या पूर्णांक से एक स्वचालित बातचीत फ्लोट करने के लिए तो यह वास्तव में पता नहीं है कि तुम क्या इरादा है कि वहाँ है। क्या आप उस विधि को कॉल करना चाहते हैं जो दो चींटियों को लेता है और एक इंट देता है, फिर इसे फ्लोट में परिवर्तित करता है या क्या आप उस विधि को कॉल करने का इरादा रखते हैं जो दो इंच लेता है और एक फ्लोट देता है? गलत विकल्प बनाने के लिए एक कंपाइलर त्रुटि होने के लिए बेहतर है और जब तक आपका एप्लिकेशन ब्रेक न हो जाए तब तक आपको सूचित न करें।

+0

एमएसआईएल यह कर सकता है, लॉल। –

+2

@devoured नहीं, यह नहीं कर सकता। एमएसआईएल का अनुमान नहीं है कि आपका मतलब क्या है; आप निर्दिष्ट करते हैं कि आपका क्या मतलब है। सी # इस मामले में निर्दिष्ट करने के लिए कोई तंत्र नहीं है। –

-3

पॉइंटर्स का उपयोग करके पैरामीटर के रूप में रिटर्न प्रकार में गुजरने के बारे में कैसे?

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

हाँ यह एक अच्छा विचार है, लेकिन वास्तव में मैंने जो नहीं पूछा है। –

+5

सी # पॉइंटर्स के बिना ऐसा कर सकता है :) – vava

+0

यह सच है, लेकिन जैसा ऊपर बताया गया है, आप वह नहीं कर सकते जो आप करना चाहते हैं। यह चारों ओर एक काम है। यह एक ही समस्या हल करता है, लेकिन एक अलग तरीके से। जब तक अन्य आवश्यकताएं नहीं हैं जिनका आपने उल्लेख नहीं किया है। यदि वहां हैं, तो हम उन्हें सुनें और हम देखेंगे कि हम इस समाधान में सुधार कर सकते हैं;) – dharga

1

नहीं, ऐसा करने के लिए कोई रास्ता नहीं है। वास्तव में, टेम्पलेट्स के साथ सी ++ को छोड़कर, कोई भी भाषा इसका समर्थन नहीं कर रही है। यह सिर्फ स्पष्ट रूप से बहुत खतरनाक है। और फिर, आप जो लिखते हैं, तो

var a = AddNumbers(1, 1); 

किस प्रकार a होने के लिए लगता है?

या क्या अगर तुम इसे पसंद

double a = AddNumbers(1, 1); 

या यहाँ तक कि

AddNumbers(1, 1); 

फोन यह कौन-सा संस्करण बुलाना चाहिए?

याद रखें, इस बारे में काफी जटिल नियम हैं कि कैसे एक प्रकार को दूसरे रूप में परिवर्तित किया जा सकता है।के साधारण प्रोग्राम पर एक नज़र है कि

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); 
    } 
} 

संकलन नहीं है कि आप इसे संकलित करने के लिए प्रयास करते हैं तो लेते हैं, तो आपको एक त्रुटि संकलक

क्योंकि
error C2668: 'parse' : ambiguous call to overloaded function 
could be 'float parse(float)' 

1,0 double टाइप किया है और संकलक वास्तव में नहीं है दे देंगे जानें कि int और float के बीच किस प्रकार का चयन करना है, इसलिए यह आपको संकेत देने के लिए कहता है। तो आप फ़ंक्शन को कॉल करने से पहले आगे बढ़ सकते हैं और एक तर्क बदल सकते हैं।

लेकिन यदि यह रिटर्न प्रकार था तो उस फ़ंक्शन को अधिभारित किया जाता है, तो आप तब ऐसा कैसे करते हैं? ऐसा करने का कोई तरीका नहीं है।

+0

पहले मामले में, यह एक चेतावनी को आग लगाएगा कि "एक्स रिटर्न टाइप माना गया"। दूसरा मामला, फ्लोट संस्करण लौटाएगा, तीसरा मामला यह पहले की तरह काम करेगा। –

+0

वैसे बड़ा मुद्दा यह है: यदि एमएसआईएल ऐसा कर सकता है, तो सी # क्यों नहीं करेगा? –

+1

कोई जानकारी नहीं है कि एमएसआईएल ऐसा क्यों करता है। शायद आप चुन सकते हैं कि आप कौन सा फ़ंक्शन चाहते हैं। लेकिन चेतावनी के साथ विचार सिर्फ गलत है। कल्पना कीजिए कि आपको दो कार्य मिलते हैं जो थोड़ा अलग दुष्प्रभाव करते हैं। कार्यक्रम तब तक अच्छा काम करता है जब तक आप किसी एक कार्य को हटा नहीं देते या तीसरे को जोड़ते हैं। और फिर सबकुछ जादुई रूप से काम करना बंद कर देता है और आप यह पता लगाने की कोशिश कर रहे हैं कि क्या हुआ है क्योंकि आपके पास पूरे सिस्टम में कीड़े हैं, जो कि अंतिम परिवर्तन से पूरी तरह से असंबंधित प्रतीत नहीं होंगे। यही कारण है कि सी ++ खतरनाक माना जाता है, यही कारण है कि जब कोई संकलक यहां तय नहीं कर सकता है तो कोई भी चेतावनी के साथ कभी नहीं जाएगा। – vava

2

एमएसआईएल एक ही असेंबली में दोनों विधियों को पकड़ने में सक्षम होने के लिए संकलक के साथ कुछ भी नहीं है जिसे निर्धारित करने के लिए कोई भी नहीं है।

कॉवरिएन्ट रिटर्न प्रकारों पर कई सालों से चर्चा की गई है, उन्हें आंशिक रूप से जावा में अनुमति दी गई है, सी ++ में एक विशेष मामला है, और सी # डिजाइनरों के पास added some minor changes to 4.0 है।

आपके खिलौने की समस्या के लिए, सरल सामान्य समाधान हैं। उदाहरण के लिए, float AddNumbers(int, int) हमेशा (float) AddNumbers(int, int) जैसा ही होने की संभावना है, इस स्थिति में दूसरे फ़ंक्शन की आवश्यकता नहीं है। आम तौर पर उस मामले को जेनेरिक के साथ संभाला जाता है: <T> AddNumbers(<T> n1, <T> n2), तो आप float AddNumbers(float, float) और int AddNumbers(int, int) के साथ समाप्त हो जाएंगे।

वास्तविक जीवन परिदृश्य होने की संभावना अधिक है जहां आपके पास अलग-अलग प्रतिनिधित्व हैं जिन्हें आप वापस करना चाहते हैं लेकिन आप विधि का नाम बदलना नहीं चाहते हैं। विरासत/ओवरराइड उपयोग मामले में, आप यह somewhat with generics भी हल कर सकते हैं।

कुछ मामलों में, जहां मैं वांछित करना चाहता हूं, वैसे ही यह वास्तव में विधियों को अधिक उपयुक्त तरीके से नामित करने के लिए बेहतर हो गया है क्योंकि यह लंबे समय तक अधिक पठनीय और रखरखाव योग्य है।

इस पर भी पहले से ही here पर चर्चा की गई थी।

में MSIL/सी # मामला http://blogs.msdn.com/abhinaba/archive/2005/10/07/478221.aspx में खास है क्योंकि वे स्पष्ट रूपांतरण ऑपरेटरों रहे हैं।

+0

और न ही किसी ने यह कहा था। –

+0

क्या आप लिंक किए गए पेज के किस बिट को हाइलाइट कर सकते हैं "संकेत देता है कि यह आ सकता है"? –

+0

केवल 4.0 परिवर्तनों का जिक्र करने के लिए सही शब्दलेखन। –

21

ECMA-334 सी # धारा 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.

आप एक सामान्य विधि इस्तेमाल कर सकते हैं:

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

एक सामान्य विधि का उपयोग ऐसा करने का एक अच्छा तरीका है। – acarlon

संबंधित मुद्दे