2012-02-29 8 views
6

संबंधित प्रश्न: Accessing a Class property without using dot operatorमेरी कक्षा Int64 के लिए, डबल आदि कास्टिंग

मैं एक वर्ग MyDouble बुलाया बना लिया है इस

class MyDouble 
{ 
    double value; 
    //overloaded operators and methods 
} 

मैं MyDouble पर कार्रवाई के सभी प्रकार करने में सक्षम हूँ की तरह लग रहा है। उदाहरण:

MyDouble a = 5.0; 
a += 3.0; 
...etc 

बहरहाल, यह अभी भी त्रुटि

MyDouble a = 5.0; 
long b = (Int64)a; //error 
long b = (int64)a.value; //works 

मैं इसे कैसे इस तरह के (Int64)a की तरह एक ऑपरेशन स्वचालित रूप से (Int64)a.value में धर्मान्तरित कि परिभाषित कर सकते हैं फेंकता है? मैं नहीं चाहता कि उपयोगकर्ता को value संपत्ति के अस्तित्व के बारे में चिंता करने की ज़रूरत है।

+0

आप 'long' और 'Int64' दोनों का उपयोग क्यों करते हैं? एक दूसरे के लिए एक अलौकिक है और मुझे लगता है कि उपनाम का उपयोग उपनामों का उपयोग करना है यदि वे प्रकार के नामों के बजाय मौजूद हैं। – Joey

उत्तर

9

इस रूपांतरण के लिए काम करने के लिए, आपको Int12 में explicit conversion की आवश्यकता होगी।

class MyDouble 
{ 
    double value; 

    public static explicit operator Int64(MyDouble value) 
    { 
     return (Int64)value.value; 
    } 
} 
+0

बिल्कुल सही, धन्यवाद। – xbonez

+0

इसे स्पष्ट क्यों होना चाहिए? एक निहित रूपांतरण भी काम करता है और कास्ट वैकल्पिक हो जाता है। – Jay

+0

@Jay आप * एक निहित ऑपरेशन कर सकते हैं, लेकिन ओपी ने रूपांतरण ऑपरेटर समेत दिखाया। निजी तौर पर, मैं निहित रूपांतरणों से बचने की कोशिश करता हूं जब तक कि वे बहुत अधिक समझ नहीं लेते (स्पष्ट रूप से दो से लंबे समय तक परिवर्तित होकर एक बुरा विचार लगता है)। –

1

अपनी कक्षा से Int64 के लिए Int64 करने के लिए डबल से एक स्पष्ट रूपांतरण नहीं है, लेकिन नहीं:

यह कैसा दिखेगा। आपको बस एक को परिभाषित करना है। या, यदि आपके पास कक्षा से दोगुनी रूपांतरण है, जो मुझे लगता है कि आप ऐसा करते हैं, तो आप यह कर सकते हैं:

लंबा x = (लंबा) (डबल) ए;

हालांकि, यह बोझिल है; मैं स्पष्ट रूपांतरण ऑपरेटर को परिभाषित करता हूं।

रूपांतरण स्पष्ट होना चाहिए, निहित नहीं, जब तक कि आपके पास इसे स्पष्ट करने का कोई अच्छा कारण न हो।

भाषा से परिभाषित रूपांतरण डबल से लंबे समय तक स्पष्ट स्पष्ट है क्योंकि रूपांतरण सूचना हानि का कारण बन सकता है। आप इस रूपांतरण के साथ जानकारी खो सकते हैं क्योंकि कुछ युगल हैं, जैसे 0.5, जो वास्तव में लंबे समय तक परिवर्तित नहीं होते हैं। इसे संकीर्ण रूपांतरण कहा जाता है।

भाषा परिभाषित रूपांतरणों के साथ, रूपांतरण को संकुचित करना स्पष्ट है। अगर वे निहित थे, तो प्रोग्रामर एक प्रकार के मूल्य को दूसरे प्रकार के चर के लिए असाइन करके जानकारी खो सकते हैं। इस रूपांतरण को परिभाषित करने के रूप में परिभाषित करने से पूरी तरह से समझदार सिद्धांत का उल्लंघन होता है, इसलिए ऐसा करने के लिए कुछ आकर्षक मामले होना चाहिए।

यहां एक उदाहरण है जो इस सिद्धांत के मूल्य को दिखा रहा है। यदि रूपांतरण को संकुचित करना निहित था, तो यह कोड को और अधिक भंगुर बना देगा। मान लें कि डबल-टू-इंट रूपांतरण अंतर्निहित है:

class Family 
{ 
    ICollection<Person> Children { get; set; } 
} 

int GetAverageNumberOfChildren(IEnumerable<Family> families) 
{ 
    return families.Sum(f => f.Children.Count)/families.Count(); 
} 

void SomeMethod(IEnumerable<Family> families) 
{ 
    int averageNumberOfChildren = GetAverageNumberOfChildren(families); 
    //... 
} 

ओह! हमारे पास एक बग है! GetAverageNumberOfChildren एक डबल वापस करना चाहिए! आइए इसे ठीक करें!

double GetAverageNumberOfChildren(IEnumerable<Family> families) 
{ 
    return families.Average(f => f.Children.Count); 
} 

व्हील, सब कुछ संकलित और चलाता है! निश्चित रूप से खुशी है कि हम उस बग को पकड़ा!

लेकिन, दुख की बात है, नहीं। हमारे पास अभी भी एक बग है!SomeMethod अंतर्निहित रूप से डबल से एक int को परिवर्तित करता है, इसलिए जहां अपेक्षित मान 2.4 हो सकता है, वास्तविक मान 2 है।

क्योंकि डबल-टू-इंट रूपांतरण स्पष्ट है, संकलक हमें स्वयं से बचाता है। GetAverageNumberOfChildren, को ठीक करने के बाद गलत प्रोग्राम संकलित नहीं होता है।

अब, अगर आपके MyDouble वर्ग कुछ मान्यता है कि यह एक सीमा के बराबर या long की सीमा की तुलना में छोटे के साथ मूल्यों पूर्णांक तक ही सीमित था, तो आप सुरक्षित रूपांतरण निहित बनाने के लिए किया जाएगा। लेकिन उस स्थिति में, निश्चित रूप से, आपको long का उपयोग करना चाहिए, double नहीं।

1

एक निहित रूपांतरण काम करेगा साथ ही एक स्पष्ट रूपांतरण भी।

public static implicit operator long(MyDouble m) 
{ 
    return (long) m.value; 
} 
इस के साथ

जगह में आप कर सकते हैं:

long b = (Int64) a; 

या सिर्फ

long b = a; 

यह दर्शाया जा सके कि रूपांतरण स्पष्ट होने की जरूरत नहीं बस है। जैसा कि उल्लेख किया गया है, हालांकि, डेटा हानि की संभावना के कारण स्पष्ट होना चाहिए।

+0

यह सच है, लेकिन खतरनाक है। स्पष्टीकरण के लिए मेरा संपादित उत्तर देखें। – phoog

+0

@ फ़ूग मैं समझता हूं। मैं केवल "आपको * आवश्यकता * एक स्पष्ट रूपांतरण" भाषा के साथ समस्या उठा रहा था। – Jay

+0

पर्याप्त मेला; मैंने सोचा कि अगर हम निहित रूपांतरणों के अस्तित्व पर चर्चा कर रहे हैं, तो संकुचित रूपांतरणों को स्पष्ट करने के कारणों पर चर्चा करना बुद्धिमान होगा। अन्यथा किसी ऐसे रूपांतरण को लागू करने के लिए प्रेरित किया जा सकता है जो एक अंतर्निहित रूपांतरण के रूप में स्पष्ट होना चाहिए "क्योंकि यह आसान है" या "क्योंकि यह मेरा कोड क्लीनर बनाता है", बिना बग्गी कार्यक्रमों की बढ़ती संभावना पर विचार किए। – phoog

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