2009-06-09 12 views
7

मुझे यकीन नहीं है कि मैं यहां क्या कर रहा हूं। मैं एक सामान्य वर्ग है, जो मूल रूप से एक महिमा पूर्णांक है, कुछ स्ट्रिंग प्रारूपण के लिए कुछ तरीकों के साथ, साथ ही साथ में/स्ट्रिंग से है और रूपांतरण int:सी # में विरासत/स्पष्ट रूपांतरण विधियां विरासत में मिली हैं?

public class Base 
{ 
    protected int m_value; 
    ... 
    // From int 
    public static implicit operator Base(int Value) 
    { 
     return new Base(Value); 
    } 
    ... 
    // To string 
    public static explicit operator string(Base Value) 
    { 
     return String.Format("${0:X6}", (int)Value); 
    } 
} 

और यह ठीक काम करता है। मैं सफलतापूर्वक निहित और स्पष्ट रूपांतरण का उपयोग कर सकते हैं:

Base b = 1; 
Console.WriteLine((string)b); // Outputs "$000001", as expected. 

तब मैं इस वर्ग से निकाले जाते हैं, अलग बच्चे कक्षाएं, जो m_value में/बंद अलग नाम दिया बिट्स को चालू करें। उदाहरण के लिए:

public class Derived : Base 
{ 

} 

और फिर मैं उपयोग नहीं कर सकते मेरी निहित करने के लिए/रूपांतरण पूर्णांक से:

Derived d = (int)3; 

अंतर्निहित/स्पष्ट रूपांतरण कर रहे हैं:

Derived d = 3; 
// Cannot implicitly convert type 'int' to 'Derived'. An explicit conversion exists (are you missing a cast?) 

यहां तक ​​कि इस एक ही त्रुटि देता है व्युत्पन्न कक्षा में विरासत में नहीं मिला? यदि नहीं, तो इसके लिए बहुत सी कोड कॉपी करने की आवश्यकता होगी।

RESPONSE त्वरित प्रतिक्रियाओं के लिए बहुत बहुत धन्यवाद! आप सभी 'उत्तर' चेकमार्क के लायक हैं, वे सभी बहुत अच्छे जवाब हैं। कुंजी बराबर चिह्न के दोनों किनारों के प्रकारों के बारे में सोचना है। अब जब मैं इसके बारे में सोचता हूं, तो यह सही समझ में आता है।

मुझे स्पष्ट रूप से केवल "व्युत्पन्न" रूपांतरणों को फिर से लिखना होगा। "Int32, स्ट्रिंग, आदि" रूपांतरण अभी भी लागू होते हैं।

+1

कैसे यह सब काम करता है, तो आप इस विषय पर मेरे लेख पढ़ने के लिए चाहते हो सकता है की बारीकियों से कुछ के बारे में अधिक जानकारी के लिए: http://blogs.msdn.com/ericlippert/archive/2007/04/16 /chained-user-defined-explicit-conversions-in-c.aspx –

उत्तर

6

कारण

Derived d = (int)3; 

काम नहीं करता है, क्योंकि प्रकार Derived बिल्कुल ऑपरेटर Base के रिटर्न मान से मेल नहीं खाता के रूप में इस ऑपरेटर को लागू करने की आवश्यकता है। ध्यान दें कि आपने कोई रूपांतरण ऑपरेटर प्रदान नहीं किया है जिसमें कोड new Derived(...) है, इसलिए यह आश्चर्य की बात नहीं है कि आप इस तरह के नए Derived उदाहरण नहीं बना सकते हैं।

हालांकि, ध्यान रखें कि विपरीत रूपांतरण

Derived v = ...; 
string s = (string)v; 

तरीके से कार्य करेंगे (जैसे कि यह कर रहे थे "प्राप्त" किया है, हालांकि यह वास्तव में विरासत static कीवर्ड की वजह से नहीं है)।

+1

मुझे नहीं लगता कि ओपी के वांछित व्यवहार को पाने का कोई तरीका है? – weberc2

3

नहीं, यह इस तरह से काम नहीं करेगा। कंपाइलर आपके लिए व्युत्पन्न आधार से अंतर्निहित डाउनकास्ट नहीं होगा। मूल रूप से, आप ऐसा नहीं कर सकते ...

D d = new B(); 

आप अपने स्ट्रिंग कलाकारों से अपने आधार वर्ग implmentations मिल जाएगा क्योंकि यह आप के लिए निहित upcasting करेंगे।

तुम एक काम के आसपास कर सकता है अगर आप अपने तरीकों अपने व्युत्पन्न वर्ग के लिए की तरह (अपने व्युत्पन्न वर्ग संभालने डी कहा जाता है), पूर्णांकों पर एक विस्तार के समारोह के साथ कॉपी करने के लिए नहीं करना चाहता था ...

public static class Ext 
{ 
    public static D IntAsD(this int val) 
    { 
     return new D(val); 
    } 
} 

उसके बाद, आप यह सही नहीं है क्या आप के साथ चाहते हो सकता है ...

D d1 = 5.IntAsD(); 

दी, है, लेकिन यह आपकी आवश्यकताओं को हो सकता है।

2

अधिभारित ऑपरेटर (रूपांतरण सहित) विरासत में हैं, लेकिन ऐसा नहीं है कि आप उन्हें अपेक्षा करते हैं। विशेष रूप से, वे व्युत्पन्न प्रकारों पर काम करने के लिए जादुई रूप से विस्तारित नहीं होते हैं। फिर से अपने कोड पर नजर डालते हैं:

Derived d = 3; 

इस बिंदु संकलक, साथ System.Int32, और व्युत्पन्न काम करने के लिए दो वर्गों है पर। तो यह उन वर्गों में रूपांतरण ऑपरेटरों की तलाश में है। यह विरासत में मिला है उन लोगों द्वारा बेस से व्युत्पन्न पर विचार करेगी, अर्थात्:

public static implicit operator Base(int Value); 
public static explicit operator string(Base Value); 

दूसरे से मेल नहीं खाता क्योंकि तर्क कोई Int32 होना चाहिए। पहला तर्क तर्क से मेल खाता है, लेकिन फिर इसका रिटर्न टाइप बेस है, और वह मेल नहीं खाता है। दूसरी ओर, यदि आप इस लिख सकते हैं:

string s = (string) new Derived(); 

और यह काम करेंगे, क्योंकि बेस में स्पष्ट ऑपरेटर मौजूद है और (जो भी लागू है तर्क बेस, बेस से व्युत्पन्न inherits होने की उम्मीद है और इसलिए तर्क प्रकार से मेल खाता)।

कारण यह है कि संकलक स्वचालित रूप से व्युत्पन्न प्रकारों में रूपांतरण ऑपरेटरों को "ठीक से" में फिर से परिभाषित नहीं करेगा क्योंकि ऐसा करने का कोई सामान्य तरीका नहीं है।

0

नहीं वे नहीं हैं। यहाँ सुराग है:

public **static** implicit operator Base(int Value)

सी # में स्थिर तरीकों निजी वर्ग के सदस्यों के उपयोग के साथ सिर्फ वैश्विक कार्य हैं। उन्हें कभी भी विरासत में नहीं मिला

+3

हालांकि यह सही है कि स्थैतिक विधियों को विरासत में नहीं मिला है, यह इस प्रश्न के लिए पूरी तरह से अप्रासंगिक है। सी # 3.0 spec का प्रासंगिक खंड खंड 6.4 है।3, जहां हम वर्णन करते हैं कि स्थिर ऑपरेटरों के लिए किस प्रकार की खोज की जाती है: "इस सेट में स्रोत प्रकार और इसके आधार वर्ग और लक्ष्य प्रकार और इसके आधार वर्ग शामिल हैं"। –

+1

ओह। मैं गलत जवाब हटा दूंगा लेकिन आपकी टिप्पणी अच्छी तरह से रखने योग्य है, इसलिए मुझे बुरा दिखने के लिए वहां रहना होगा :-) –

1

रूपांतरण/ऑपरेटर विधियां एक सुविधा है लेकिन जैसा कि अन्य ने ध्यान दिया है, वे हमेशा जो भी आप चाहते हैं वह करने के लिए नहीं जा रहे हैं। विशेष रूप से, यदि कंपाइलर = चिह्न के दोनों किनारों पर सही प्रकार नहीं देखता है, तो यह आपके रूपांतरण/ऑपरेटर पर भी विचार नहीं करेगा। यही कारण है कि अगर आप निम्न उपाय अपनाते हैं आप एक संकलक चेतावनी मिलती है:

object str = "hello"; 
if (str == "hello") { 
} 

इसके अलावा, कस्टम रूपांतरण का उपयोग करते समय के रूप में/कीवर्ड्स है माना जाता है।

एक स्पष्ट/निहित रूपांतरण को लागू करने के बारे में सोचते समय, आपको IConvertible और/या टाइपकॉन्टर को कार्यान्वित करने पर भी विचार करना चाहिए। बेस क्लास हैंडल प्रकार रूपांतरण होने पर यह आपको बहुत अधिक लचीलापन देता है।

0

जबकि आप इसे सीधे नहीं कर सकते हैं, कुछ छोटे कटौती हैं जिनका उपयोग आप कोड-पुन: उपयोग को सक्षम करने के लिए कर सकते हैं।

public class Base 
{ 
    protected int m_value; 
    ... 
    // From int 
    public static implicit operator Base(int Value) 
    { 
     Base newObject = new Base(); 
     newObject.FromInt(Value); 
     return newObject; 
    } 
    ... 
    // To string 
    public static explicit operator string(Base Value) 
    { 
     return String.Format("${0:X6}", (int)Value); 
    } 

    //Instance FromInt() 
    protected void FromInt(int value) 
    { 
     m_value = value; 
    } 
} 

public class Derived : Base 
{ 
    // To string, re-use Base-ToString 
    public static explicit operator string(Derived Value) 
    { 
     // Cast (Derived)Value to (Base)Value and use implemented (Base)toString 
     return (string)(Base)Value; 
    } 

    // Use FromInt, which has access to instance variables 
    public static implicit operator Base(int Value) 
    { 
     // We can't use (Base)obj = Value because it will create 
     // a "new Base()" not a "new Derived()" 
     Derived newObject = new Derived(); 
     newObject.FromInt(Value); 
     return newObject; 
    } 
} 
संबंधित मुद्दे