2013-08-29 3 views
7

मैं दो वर्गों FirstProcess और दूसरा प्रक्रियासी #: वैकल्पिक पैरामीटर और नामित मानकों के साथ अधिभावी विधि: अनपेक्षित परिणाम

public class FirstProcess 
    { 
     public virtual void Calculate(int x, int y) 
     { 
      Console.WriteLine("First Process X :{0} and Y{1}", x, y); 
     } 
    } 
    public class SecondProcess : FirstProcess 
    { 

     public override void Calculate(int y, int x) 
     { 
      Console.WriteLine("Second Process X :{0} and Y :{1}", x, y); 
     } 
    } 

मैं की तरह कैलकुलेट प्रणाली कहा जाता है है नीचे

var secondProcess = new SecondProcess(); 
      var firstProcess = (FirstProcess) secondProcess; 

      secondProcess.Calculate(x: 1, y: 2); 
      firstProcess.Calculate(x: 1, y: 2); 

आउटपुट

दूसरी प्रक्रिया एक्स: 1 और वाई: 2

दूसरी प्रक्रिया एक्स: 2 और वाई: 1

मुझे अप्रत्याशित परिणाम मिला कि एक्स = 2 और वाई = 1. कैसे .Net इस परिदृश्य को संभालते हैं? क्यों .net नामित पैरामीटर को प्राथमिकता देते हैं?

उत्तर

9

तर्क विधि कॉल firstProcess.Calculate(x: 1, y: 2) के लिए बाध्यकारी संकलन समय पर किया जाता है, लेकिन क्योंकि विधि virtual है विधि प्रेषण क्रम पर किया जाता है।

विधि कॉल को संकलित करने के लिए, कंपाइलर x: 1, y: 2 देखता है और उपयुक्त आईएल को उत्सर्जित करने के लिए अनुक्रमिक रूप से अनुक्रमित तर्क सूची में इस नामित तर्क सूची को हल करने की आवश्यकता है (सही क्रम में स्टैक पर तर्क दबाएं, फिर कॉल विधि)। firstProcess की स्थिर प्रकार है, जो FirstProcess है:

नामित तर्क सूची के अलावा वहाँ संकलक के लिए उपलब्ध जानकारी का एक और टुकड़ा है। अब मैं और आप दोनों जानते हैं कि रनटाइम पर यह SecondProcess उदाहरण होगा, लेकिन संकलक यह नहीं जानता कि (कम से कम सामान्य मामले में)। तो यह FirstProcess.Calculate की पैरामीटर सूची देखता है और देखता है कि x पहला तर्क है, y दूसरा है। यह यह आपके कोड संकलन के रूप में यदि आप

firstProcess.Calculate(1, 2); 

लिखा था क्रम पर बनाता है, तर्क 1 और 2 ढेर पर धकेल दिया जाता है और एक आभासी कॉल Calculate किया जाता है। बेशक यह SecondProcess.Calculate पर कॉल करना समाप्त होता है, लेकिन पैरामीटर नाम रनटाइम में संक्रमण से बच नहीं पाए हैं। SecondProcess.Calculate1 को इसके पहले तर्क (y) और 2 को इसके दूसरे तर्क (x) के रूप में स्वीकार करता है, जिसके परिणामस्वरूप परिणाम सामने आते हैं।

एक अलग रूप में के रूप में, यह भी जब आप डिफ़ॉल्ट तर्क मान का उपयोग होता है:

public class FirstProcess 
{ 
    public virtual void Calculate(int x = 10) 
    { 
     Console.WriteLine("First Process X :{0}", x); 
    } 
} 

public class SecondProcess : FirstProcess 
{ 
    public override void Calculate(int x = 20) 
    { 
     Console.WriteLine("Second Process X :{0}", x); 
    } 
} 

var secondProcess = new SecondProcess(); 
var firstProcess = (FirstProcess) secondProcess; 

secondProcess.Calculate(); // "Second Process X: 20" 
firstProcess.Calculate(); // "Second Process X: 10" 

कहानी का नैतिक: नामित और डिफ़ॉल्ट तर्क सुविधाजनक हैं, लेकिन जिस तरह से वे (जरूरी) कर रहे हैं लागू किया पत्ते आप अप्रिय आश्चर्य के लिए खोलते हैं। जब वे वास्तविक मूर्त लाभ प्रदान करते हैं, तब भी उनका उपयोग करें, जब भी आप कर सकें।

+0

+1 मैं अभी इस कोड के माध्यम से कदम उठा रहा था, वास्तव में मुझे भ्रमित कर रहा था। स्पष्टीकरण के लिए धन्यवाद। –

+0

भयानक स्पष्टीकरण .. बहुत जॉन धन्यवाद – JEMI

0

जब नाम वाले पैरामीटर को हल करने, संकलक स्थिर विधि के प्रकार का उपयोग करता है बुलाया जा रहा है, नहीं गतिशील प्रकार।

इसलिए आपके उदाहरण में, x दूसरे पैरामीटर में पहले पैरामीटर और y को संदर्भित करता है।

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