2014-09-25 6 views
11

मैं another question (थोड़ा संशोधित), मेरे कोड में उपयोग करने के लिए से कोड के नीचे उधार लिया है:ऑपरेटर को स्पष्ट रूप से निर्दिष्ट करना क्यों महत्वपूर्ण है?

internal class PositiveDouble 
{ 
     private double _value; 
     public PositiveDouble(double val) 
     { 
      if (val < 0) 
       throw new ArgumentOutOfRangeException("Value needs to be positive"); 
      _value = val; 
     } 

     // This conversion is safe, we can make it implicit 
     public static implicit operator double(PositiveDouble d) 
     { 
      return d._value; 
     } 
     // This conversion is not always safe, so we're supposed to make it explicit 
     public static explicit operator PositiveDouble(double d) 
     { 
      return new PositiveDouble(d); // this constructor might throw exception 
     } 
} 

इस कोड के मूल लेखक सही ढंग से MSDN के implicit & explicit दस्तावेज में दिए गए चेतावनी का पालन करता है, लेकिन यहाँ है मेरा प्रश्न: explicit संभावित रूप से असाधारण कोड में हमेशा आवश्यक है?

तो, मैं कुछ प्रकार मेरी कोड में मिल गया है (उदाहरण के लिए "वॉल्यूम") है कि PositiveDouble और मैं नीचे से निकाले जाते हैं पहली पंक्ति की तरह आसानी से उदाहरणों सेट करने में सक्षम होना चाहते हैं:

Volume v = 10; //only allowed by implicit conversion 
Volume v = new Volume(10) //required by explicit conversion, but gets messy quick 

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

+0

मुझे निहित के लिए आपके रूपांतरण ऑपरेटर बदलने के यहाँ ठीक किया जाना चाहिए करने के लिए लगता है। – Botonomous

+1

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

उत्तर

14

सी # भाषा विनिर्देश 10.10.3 रूपांतरण ऑपरेटरों के तहत कहते हैं:

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

इसके अलावा, MSDN: implicit (C# Reference) से:

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

इस ध्यान में रखते हुए अपने operator PositiveDouble(double d)implicit नहीं चिह्नित किया जाना चाहिए, के रूप में Volume v = -1 एक अपवाद फेंक देते हैं।

हमेशा स्पष्ट संभावित असाधारण कोड में जरूरी है:

तो आपके प्रश्न का उत्तर के लिए?

नहीं, यह आवश्यक नहीं है, लेकिन यह चाहिए

राय-आधारित पर सीमा: यदि आपके कोड केवल कोड इस रूपांतरण का उपयोग है, और आप अंतर्निहित रूपांतरण पढ़ने में आसान और/या बनाए रखने, कि उपयोग करने के लिए स्वतंत्र लग रहा है लगता है।

कैसे यह उपयोगकर्ता की रक्षा करता है के रूप में?

MSDN: explicit (C# Reference) देखें उल्लेख है: एक रूपांतरण आपरेशन अपवाद कारण या जानकारी खो सकते हैं

हैं, तो आप यह स्पष्ट निशान चाहिए। यह संकलक को संभावित रूप से अप्रत्याशित परिणामों के साथ रूपांतरण संचालन को चुपचाप आक्रमण से रोकता है।

जब यह होता है तो मैं वास्तव में समझ नहीं पा रहा हूं, लेकिन फिर, अगर आपको लगता है कि आप कभी भी अपने कोड में नकारात्मक डबल से कनवर्ट नहीं करते हैं, तो इसे कभी फेंकना नहीं चाहिए।

+2

* "मैं वास्तव में नहीं जान सकता है जब यह घटित होता" * - यह आसानी से जब ढांचा तरीकों कि इस तरह के तर्क को स्वीकार करने के लिए कस्टम रूपांतरण के साथ वस्तुओं गुजर हो सकता है। यह वास्तव में कोड में स्पष्ट है कि ऐसा होगा जब तक आप (क) पता है कि वास्तव में क्या तर्क प्रकार (ओं) ढांचे विधि स्वीकार करता है, और (ख) पता है कि निहित रूपांतरण मौजूद नहीं है। – cdhowie

13

रूपांतरण केवल तभी निहित होना चाहिए जब वे हमेशा सफल होंगे। यदि वे असफल हो सकते हैं या जानकारी का नुकसान कर सकते हैं, तो उन्हें स्पष्ट होना चाहिए, क्योंकि इसके लिए रूपांतरण ऑपरेशन के कॉलर को जानबूझकर संकेत मिलता है कि वे यह रूपांतरण चाहते हैं और इसलिए परिणाम से निपटने के लिए तैयार हैं, जो भी हो सकता है।

हम इसे फ्रेमवर्क आदिम संख्यात्मक प्रकारों में देख सकते हैं; int को long पर असाइन करना एक निहित रूपांतरण है, क्योंकि यह हमेशा इच्छित परिणाम के साथ सफल रहेगा। दूसरी तरफ जाकर चेक किए गए संदर्भ में OverflowException का कारण बन सकता है, और अनचेक संदर्भ में छंटनी (सूचना का नुकसान) का कारण बन सकता है, इसलिए आपको यह इंगित करना होगा कि आपने स्पष्ट रूप से कास्टिंग करके इस रूपांतरण का इरादा किया है।

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