2011-11-13 12 views
9

मेरा दिमाग जेली हो गया है, या मेरे पास दिमागी अनुभव, या कुछ से बाहर है। मैं एक वर्ग पदानुक्रम है कि लग रहा है को संवारता कर रहा हूँ इस तरह एक सा:
enter image description hereऑपरेटर और विरासत

मेरे Money वर्ग इस तरह दिखता है:

public abstract class Money 
{ 
    public int Amount { get; set; } 

    public static bool operator ==(Money leftSide, Money rightSide) 
    { 
     // Money can only be equal if it is in the same currency. 
     if (leftSide.GetType() != rightSide.GetType()) return false; 
     return leftSide.Amount == rightSide.Amount; 
    } 

    public static bool operator !=(Money leftSide, Money rightSide) 
    { 
     // If the currencies are different, the amounts are always considered unequal. 
     if (leftSide.GetType() != rightSide.GetType()) return true; 
     return leftSide.Amount != rightSide.Amount; 
    } 

    public static Money operator *(Money multiplicand, int multiplier) 
    { 
     var result = multiplicand * multiplier; 
     return result; 
    } 

    public static Dollar Dollar(int amount) 
    { 
     return new Dollar(amount); 
    } 

    public static Franc Franc(int amount) 
    { 
     return new Franc(amount); 
    } 
} 

मेरे डॉलर operator * इस तरह दिखता है:

public static Dollar operator *(Dollar multiplicand, int multiplier) 
{ 
    var result = multiplicand.Amount * multiplier; 
    return new Dollar(result); 
} 

अब, अगर मैं यह टेस्ट कोड चलाता हूं, तो मुझे स्टैक ओवरफ़्लो मिलता है (वाहू!)

{ 
    Money fiveDollars = Money.Dollar(5); 
    Money timesTwo = fiveDollars*2; 
} 

मुझे उम्मीद थी कि यह फिर से उप-वर्ग (डॉलर) operator * पर कॉल करेगा, जो एक निश्चित परिणाम लौटाएगा क्योंकि (डॉलर * int) को गैर-पुनरावर्ती रूप से परिभाषित किया गया है। चूंकि यह काम नहीं करता है, वैकल्पिक यह है कि मैंने कुछ गूंगा किया है। यह क्यों काम नहीं करता है? इस व्यवहार को पाने का सही तरीका क्या होगा?

+1

जब आपको स्टैक ओवरफ़्लो मिलता है, तो आपको स्टैक की जांच करनी चाहिए। आप एक ही काम को एक-दूसरे को बार-बार बुलाएंगे। वह अकेला आपको बताएगा कि क्या हो रहा है और क्यों। – abelenky

+2

ध्यान दें कि रिकर्सन होता है क्योंकि आप वास्तव में 'मनीऑपरेटर *' का आह्वान कर रहे हैं, न कि 'डॉलर। ऑपरेटर *'। ऑपरेटर * अधिभारित *, * ओवरराइड * नहीं होते हैं, और इसलिए जो कार्यवाही की जाती है उसे * संकलन-समय * ऑपरेंड के प्रकारों द्वारा निर्धारित किया जाता है, न कि * रन-टाइम * प्रकार। चूंकि 'पांच डोलर्स 'प्रकार' मनी 'का एक चर है,' पांच डोलर्स * 2' 'ऑपरेटर *' के 'मनी' संस्करण को आमंत्रित करता है (भले ही * रन-टाइम *' पांच डोलर्स 'प्रकार 'डॉलर' है।) – dlev

उत्तर

11

आप .Amount

public static Money operator *(Money multiplicand, int multiplier) 
{ 
    var result = multiplicand.Amount * multiplier; 
    return result; 
} 
+0

+1 धन्यवाद, अच्छी पकड़ –

4

समस्या को छोड़ दिया है लगता है आप उम्मीद करते हैं कि यह है कि आप ओवरराइड व्युत्पन्न वर्ग में ऑपरेटरों और उम्मीद कर सकते हैं dynamic binding है। यह सी # में काम नहीं करता है। ऑपरेटर ओवरलोडेड और वास्तविक अधिभार को संकलित-समय चुना जाता है। इसका मतलब है कि निम्नलिखित कोड पुनरावर्ती है और खुद को कहता है:

public static Money operator *(Money multiplicand, int multiplier) 
{ 
    var result = multiplicand * multiplier; 
    return result; 
} 

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

int a = 5; 
int b = 5; 

Console.WriteLine(a == b); // true 
Console.WriteLine(a.Equals(b)); // true 
Console.WriteLine((object)a == (object)b); // false 
Console.WriteLine(((object)a).Equals((object)b)); // true 

तीसरे मामले में, सी # a और b पूर्णांक की बजाय ऑब्जेक्ट्स के रूप में व्यवहार करता है, इसलिए यह ऑब्जेक्ट्स के लिए उपयोग किए जाने वाले डिफ़ॉल्ट == ऑपरेटर का उपयोग करता है: संदर्भों की तुलना करना (इस मामले में बॉक्स किए गए पूर्णांक के संदर्भ)।

यह क्लास पदानुक्रम पर ऑपरेटरों को परिभाषित करने के लिए अजीब बना सकता है जहां आप व्युत्पन्न कक्षाओं में ऑपरेटरों को फिर से परिभाषित करना चाहते हैं। यह विशेष रूप से अजीब होता है जब व्यवहार दोनों ऑपरेटरों के संयोजन पर निर्भर करता है, क्योंकि सी # (और अधिकांश अन्य ओओपी भाषाओं) में multiple dispatch के लिए समर्थन नहीं है। आप आगंतुक पैटर्न का उपयोग कर इसे हल कर सकते हैं, लेकिन मुझे लगता है कि इस मामले में आपको पुनर्विचार करना चाहिए यदि प्रत्येक मुद्रा के लिए उप-वर्गों का उपयोग करना सबसे अच्छा समाधान है।

+0

+1 हां, यह वास्तव में समस्या प्रतीत होता है। मैं _did_ लगता है ऑपरेटरों को ओवरराइड किया गया था, मैंने यहाँ कुछ सीखा है :) –

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