मुझे C # के अंतर्निहित प्रकार रूपांतरण ऑपरेटर का उपयोग कब करना चाहिए?


14

C # में, हम इस तरह निहित रूपांतरण ऑपरेटर को अधिभारित कर सकते हैं (उदाहरण MSDN से ):

struct Digit
{
    /* ... */
    public static implicit operator byte(Digit d)  // implicit digit to byte conversion operator
    {
        /* ... */
    }
}

इस प्रकार, हमारे पास एक प्रकार हो सकता है, एक कस्टम मूल्य प्रकार , जादुई रूप से खुद को दूसरे (असंबंधित) प्रकार में परिवर्तित करना, दर्शकों को घबराहट में छोड़ देना (जब तक कि वे बैकस्ट में सहकर्मी न हों और अंतर्निहित रूपांतरण ऑपरेटर देखें, वह है)।

मुझे किसी को भी छोड़ना पसंद नहीं है जो मेरे कोड को घबराहट में पढ़ता है। मुझे नहीं लगता कि बहुत से लोग करते हैं।

सवाल यह है कि निहित प्रकार के रूपांतरण ऑपरेटर के उपयोग-मामले क्या हैं, जो मेरे कोड को समझने में अधिक कठिन नहीं होगा?


1
वाह। मैं वास्तव में नहीं जानता था कि यह अस्तित्व में है। ऐसा नहीं है कि यह आवश्यक रूप से उपयोग करने के लिए एक अच्छी बात है; मुझे पता है कि C ++ में इस तरह की कार्यक्षमता-छिपाना पर लोग वास्तव में नाराज हो गए थे।
कटाना ३१४

@ Katana314: यह वह नहीं था, जिसके बारे में लोग नाराज़ थे, लेकिन किसी ने अधिभार व्यवहार के साथ अधिभार (यह ऑपरेटर, रूपांतरण-फ़ंक्शन, निर्माता, नि: शुल्क फ़ंक्शन या सदस्य-कार्य) हो, अधिमानतः आश्चर्यजनक रूप से जोड़ दिया।
Deduplicator

मैं आपको C ++ में "ऑपरेटर ओवरलोडिंग" पर पढ़ने की सलाह देता हूं, विशेष रूप से "कास्टिंग" ऑपरेटरों। मुझे लगता है कि इसके खिलाफ / के खिलाफ एक ही तर्क के कई तर्क समान हैं, सिवाय इसके कि बहस तीन बार चल रही है जब तक कि C # पढ़ने के लिए बहुत अधिक मौजूद है।

जवाबों:


18

मैं केवल उन प्रकारों के बीच निहित रूपांतरणों की सिफारिश करूंगा जो विभिन्न तरीकों से समान मूल्यों का प्रतिनिधित्व करते हैं। उदाहरण के लिए:

  • अलग रंग प्रकार की तरह है RGB, HSL, HSVऔर CMYK
  • एक ही भौतिक मात्रा ( Meterबनाम Inch) के लिए अलग-अलग इकाइयाँ ।
  • विभिन्न समन्वय प्रणाली (ध्रुवीय बनाम कार्टेशियन)।

हालांकि, कुछ मजबूत दिशानिर्देश हैं जो इंगित करते हैं कि जब एक अंतर्निहित रूपांतरण को परिभाषित करना उचित नहीं है :

  • यदि रूपांतरण सटीकता या सीमा का एक महत्वपूर्ण नुकसान का कारण बनता है, तो इसे निहित नहीं किया जाना चाहिए (जैसे: फ्लोट64 से फ्लोट 32 तक या लंबे समय तक इंट से)।
  • यदि रूपांतरण InvalidCastअपवाद ( ) अपवाद को फेंक सकता है, तो इसे निहित नहीं किया जाना चाहिए।
  • यदि रूपांतरण हर बार किए जाने पर ढेर आवंटन का कारण बनता है, तो इसे निहित नहीं किया जाना चाहिए।
  • यदि रूपांतरण एक O(1)ऑपरेशन नहीं है , तो इसे निहित नहीं किया जाना चाहिए।
  • यदि स्रोत प्रकार या लक्ष्य प्रकार परस्पर है, तो रूपांतरण निहित नहीं होना चाहिए।
  • यदि रूपांतरण किसी प्रकार के संदर्भ (डेटाबेस, संस्कृति सेटिंग्स, कॉन्फ़िगरेशन, फ़ाइल सिस्टम, आदि) पर निर्भर है, तो इसे निहित नहीं किया जाना चाहिए (मैं इस मामले में एक स्पष्ट रूपांतरण ऑपरेटर को भी हतोत्साहित करूंगा)।

अब कहें कि आपका रूपांतरण ऑपरेटर f: T1 -> T2ऊपर दिए गए किसी भी नियम का उल्लंघन नहीं करता है, तो निम्न व्यवहार दृढ़ता से इंगित करता है कि रूपांतरण निहित हो सकता है:

  • अगर है a == bतो f(a) == f(b)
  • अगर है a != bतो f(a) != f(b)
  • अगर है a.ToString() == b.ToString()तो f(a).ToString() == f(b).ToString()
  • अन्य कार्यों है कि दोनों पर परिभाषित कर रहे हैं के लिए आदि T1और T2

आपके सभी उदाहरण संभवतः हानिपूर्ण हैं। चाहे वे वैसे भी पर्याप्त रूप से सटीक हों, ...
डिडुप्लिकेटर

हाँ मुझे एहसास हुआ कि :-)। मैं "हानिपूर्ण" के लिए एक बेहतर शब्द नहीं सोच सकता था। "हानिपूर्ण" से मेरा अभिप्राय उन रूपांतरणों से है जहां सीमा या सटीकता काफी कम हो गई है। जैसे कि फ्लोट64 से फ्लोट 32 या लंबे समय से इंट तक।
एलियान एबिंग

मुझे लगता है कि एक = = बी => एफ (ए)! = एफ (बी), शायद लागू नहीं होना चाहिए। ऐसे बहुत सारे कार्य हैं जो अलग-अलग इनपुट्स के लिए समान मान लौटा सकते हैं, फर्श () और छत () उदाहरण के लिए गणित पक्ष पर
cdkMoose

@cdkMoose आप निश्चित रूप से सही हैं, और इसलिए मैं इन गुणों को "बोनस अंक" के रूप में देखता हूं, नियम नहीं। दूसरी संपत्ति का सीधा सा मतलब है कि रूपांतरण फ़ंक्शन इंजेक्टिव है। यह अक्सर ऐसा होता है जब आप एक ऐसे प्रकार में परिवर्तित होते हैं जिसमें एक बड़ी रेंज होती है, जैसे int32 से int64 तक।
एलियन एबिंग

दूसरी ओर @cdkMoose, पहली संपत्ति में कहा गया है कि एक ही तुल्यता वर्ग के भीतर दो मान T1( ==संबंध पर निहित T1) हमेशा एक ही समतुल्य वर्ग के भीतर दो मानों के लिए मैप करते हैं T2। अब जब मैं इसके बारे में सोचता हूं, तो मुझे लगता है कि पहली संपत्ति वास्तव में एक अंतर्निहित रूपांतरण के लिए आवश्यक होनी चाहिए।
एलियन एबिंग

6

सवाल यह है कि निहित प्रकार के रूपांतरण ऑपरेटर के उपयोग-मामले क्या हैं, जो मेरे कोड को समझने में अधिक कठिन नहीं होगा?

जब प्रकार असंबंधित नहीं हैं (प्रोग्रामर के लिए)। ऐसे (दुर्लभ) परिदृश्य हैं जहां आपके दो असंबंधित प्रकार हैं (जहाँ तक कोड का संबंध है), जो वास्तव में संबंधित हैं (जहाँ तक डोमेन या उचित प्रोग्रामर का संबंध है)।

उदाहरण के लिए, कुछ कोड स्ट्रिंग मिलान करने के लिए। एक आम परिदृश्य एक स्ट्रिंग शाब्दिक से मेल खाता है। कॉल करने के बजाय IsMatch(input, new Literal("some string")), एक अंतर्निहित रूपांतरण आपको उस समारोह से छुटकारा दिलाता है - कोड में शोर - और स्ट्रिंग शाब्दिक पर ध्यान केंद्रित करता है।

अधिकांश कोई भी प्रोग्रामर देखेगा IsMatch(input, "some string")और जल्दी से क्या करेगा। यह कॉल साइट पर आपका कोड स्पष्ट करता है। संक्षेप में, यह समझने में थोड़ा आसान है कि क्या चल रहा है, थोड़े खर्च पर कि यह कैसे चल रहा है।

अब, आप तर्क दे सकते हैं कि एक ही कार्य करने के लिए एक साधारण कार्य अधिभार बेहतर होगा। और यह है। लेकिन अगर इस प्रकार की बात सर्वव्यापी है, तो एक रूपांतरण होने के कारण फ़ंक्शन ओवरलोड्स के ढेर करने की तुलना में क्लीनर (कम कोड, बढ़ी हुई स्थिरता) है।

और आप तर्क दे सकते हैं कि इंटरमीडिएट प्रकार को स्पष्ट रूप से बनाने के लिए प्रोग्रामर की आवश्यकता होती है, इसलिए वे देखते हैं कि "वास्तव में क्या चल रहा है"। वह कम सीधा है। व्यक्तिगत रूप से, मुझे लगता है कि "वास्तव में क्या चल रहा है" के बारे में शाब्दिक स्ट्रिंग मैच का उदाहरण बहुत स्पष्ट है - प्रोग्रामर को मैकेनिक को यह जानने की जरूरत नहीं है कि सब कुछ कैसे होता है। क्या आप जानते हैं कि आपके सभी कोड आपके द्वारा चलाए जा रहे विभिन्न प्रोसेसरों द्वारा कैसे निष्पादित होते हैं? हमेशा अमूर्तता की एक रेखा होती है जहां प्रोग्रामर इस बात की देखभाल करना बंद कर देते हैं कि कुछ कैसे काम करता है। अगर आपको लगता है कि निहित रूपांतरण कदम महत्वपूर्ण हैं, तो अंतर्निहित रूपांतरण का उपयोग न करें। यदि आपको लगता है कि वे कंप्यूटर को खुश रखने के लिए सिर्फ समारोह कर रहे हैं, और प्रोग्रामर को हर जगह उस शोर को नहीं देखना बेहतर होगा;


आपके अंतिम बिंदु को और भी आगे ले जाया जाना चाहिए: एक ऐसी रेखा भी है जिसके आगे एक प्रोग्रामर ने बहुत अच्छी तरह से लानत की थी कि कुछ कैसे किया जाता है, इस बात की परवाह न करें कि यह संविदात्मक नहीं है।
Deduplicator
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.