यहां तक कि अगर आप उन्हें किसी भी तरह देख सकते हैं, तो वे उद्देश्य में पूरी तरह से अलग हैं। आइए सबसे पहले यह परिभाषित करने का प्रयास करें कि कलाकार क्या है:
कास्टिंग एक डेटा प्रकार की इकाई को दूसरे में बदलने की क्रिया है।
यह थोड़ा सामान्य है और यह किसी भी तरह से रूपांतरण के बराबर है क्योंकि एक कास्ट में अक्सर रूपांतरण का समान सिंटैक्स होता है, इसलिए सवाल यह होना चाहिए कि भाषा द्वारा किसी कास्ट (निहित या स्पष्ट) की अनुमति है और आपको कब उपयोग करना है ( अधिक) स्पष्ट रूपांतरण?
मुझे पहले उनके बीच एक सरल रेखा खींचनी है। औपचारिक रूप से (भले ही भाषा वाक्य रचना के लिए समतुल्य हो) एक कलाकार प्रकार को बदल देगा जबकि एक रूपांतरण विल / मान बदल सकता है (अंततः प्रकार के साथ मिलकर )। साथ ही एक कास्ट प्रतिवर्ती है जबकि रूपांतरण नहीं हो सकता है।
यह विषय बहुत बड़ा है, इसलिए आइए इसे खेल से कस्टम कास्ट ऑपरेटरों को छोड़कर थोड़ा संकीर्ण करने का प्रयास करें।
निहित जाति
C # में एक कास्ट तब लगाया जाता है जब आप कोई जानकारी नहीं खोते हैं (कृपया ध्यान दें कि यह चेक प्रकारों के साथ किया जाता है न कि उनके वास्तविक मूल्यों के साथ )।
आदिम प्रकार
उदाहरण के लिए:
int tinyInteger = 10;
long bigInteger = tinyInteger;
float tinyReal = 10.0f;
double bigReal = tinyReal;
ये जातियाँ अंतर्निहित हैं क्योंकि रूपांतरण के दौरान आप किसी भी जानकारी को नहीं खोएंगे (आप केवल प्रकार को व्यापक बनाते हैं)। रूपांतरण के दौरान इसके वास्तविक मानों की परवाह किए बिना इसके विपरीत निहित कलाकारों की अनुमति नहीं है (क्योंकि उन्हें केवल रन-टाइम पर जांचा जा सकता है), रूपांतरण के दौरान आप कुछ जानकारी खो सकते हैं। उदाहरण के लिए यह कोड संकलित नहीं करेगा क्योंकि doubleइसमें (और वास्तव में ऐसा हो सकता है) एक मान का प्रतिनिधित्व करने योग्य नहीं है float:
double bigReal = Double.MaxValue;
float tinyReal = bigReal;
वस्तुओं
ऑब्जेक्ट (पॉइंटर) के मामले में, कास्ट हमेशा अंतर्निहित होता है जब कंपाइलर सुनिश्चित कर सकता है कि स्रोत प्रकार एक व्युत्पन्न वर्ग है (या यह लक्ष्य वर्ग के प्रकार को लागू करता है), उदाहरण के लिए:
string text = "123";
IFormattable formattable = text;
NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;
इस मामले में कंपाइलर जानता है कि stringलागू होता है IFormattableऔर वह NotSupportedException(इससे प्राप्त होता है) Exceptionइसलिए कास्ट निहित है। कोई जानकारी नहीं खोई है क्योंकि ऑब्जेक्ट उनके प्रकार नहीं बदलते हैं (यह structs और आदिम प्रकार के साथ अलग है क्योंकि एक कलाकार के साथ आप एक अन्य प्रकार की एक नई वस्तु बनाते हैं ), उनमें से आपके विचारों में क्या परिवर्तन होता है।
स्पष्ट जाति
एक कास्ट स्पष्ट है जब रूपांतरण संकलक द्वारा नहीं किया जाता है और फिर आपको कास्ट ऑपरेटर का उपयोग करना चाहिए। आमतौर पर इसका मतलब है कि:
- आप जानकारी या डेटा खो सकते हैं, इसलिए आपको इसके बारे में पता होना चाहिए।
- रूपांतरण विफल हो सकता है (क्योंकि आप एक प्रकार को दूसरे में परिवर्तित नहीं कर सकते हैं) इसलिए, फिर, आपको पता होना चाहिए कि आप क्या कर रहे हैं।
आदिम प्रकार
जब आप कुछ डेटा खो सकते हैं, उदाहरण के लिए, जब आदिम प्रकार के लिए एक स्पष्ट कलाकारों की आवश्यकता होती है:
double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);
float coarse = (float)precise;
float epsilon = (float)Double.Epsilon;
दोनों उदाहरणों में, भले ही मान floatसीमा के भीतर हो , आप जानकारी (इस मामले में सटीक) खो देंगे ताकि रूपांतरण स्पष्ट हो। अब यह प्रयास करें:
float max = (float)Double.MaxValue;
यह रूपांतरण विफल हो जाएगा, फिर से, यह स्पष्ट होना चाहिए ताकि आप इसके बारे में जानते हों और आप एक चेक कर सकें (उदाहरण में मान स्थिर है, लेकिन यह कुछ रन-टाइम संगणना या I / O से आ सकता है)। अपने उदाहरण पर वापस जाएं:
string text = "123";
double value = (double)text;
यह संकलित नहीं करेगा क्योंकि संकलक पाठ को संख्याओं में परिवर्तित नहीं कर सकता है। पाठ में कोई भी वर्ण हो सकते हैं, केवल संख्या नहीं और यह बहुत अधिक है, सी # में, यहां तक कि एक स्पष्ट कलाकारों के लिए (लेकिन इसे किसी अन्य भाषा में अनुमति दी जा सकती है)।
वस्तुओं
पॉइंटर्स (ऑब्जेक्ट्स से) के रूपांतरण विफल हो सकते हैं यदि प्रकार असंबंधित हैं, उदाहरण के लिए यह कोड संकलित नहीं करेगा (क्योंकि कंपाइलर जानता है कि कोई संभावित रूपांतरण नहीं है):
string text = (string)AppDomain.Current;
Exception exception = (Exception)"abc";
यह कोड संकलित करेगा लेकिन यह रन-टाइम पर विफल हो सकता है (यह प्रभावी वस्तुओं के प्रकार पर निर्भर करता है) a InvalidCastException:
object obj = GetNextObjectFromInput();
string text = (string)obj;
obj = GetNextObjectFromInput();
Exception exception = (Exception)obj;
रूपांतरण
तो, आखिरकार, यदि जाति रूपांतरण हैं, तो हमें कक्षाओं की आवश्यकता क्यों है Convert? Convertकार्यान्वयन और IConvertibleकार्यान्वयन से आने वाले सूक्ष्म अंतरों को अनदेखा करना क्योंकि सी # में एक कास्ट के साथ आप कंपाइलर को कहते हैं:
मेरा विश्वास करो, यह प्रकार उस प्रकार का है, भले ही आप इसे अब नहीं जान सकते, मुझे ऐसा करने दें और आप देखेंगे।
-या-
चिंता मत करो, मुझे परवाह नहीं है अगर इस रूपांतरण में कुछ खो जाएगा।
किसी और चीज के लिए एक अधिक स्पष्ट ऑपरेशन की आवश्यकता है ( आसान कलाकारों के निहितार्थ के बारे में सोचें , यही कारण है कि सी ++ ने उनके लिए लंबे, क्रियात्मक और स्पष्ट वाक्यविन्यास पेश किए हैं)। इसमें एक जटिल ऑपरेशन शामिल हो सकता है ( string-> doubleरूपांतरण एक पार्सिंग की आवश्यकता होगी)। stringउदाहरण के लिए, रूपांतरण हमेशा संभव होता है ( ToString()विधि के माध्यम से ) लेकिन इसका मतलब यह हो सकता है कि आप जो अपेक्षा करते हैं उससे कुछ अलग हो सकता है इसलिए यह एक कास्ट से अधिक स्पष्ट होना चाहिए ( जितना आप लिखते हैं, उतना ही आप जो कर रहे हैं उसके बारे में सोचते हैं )।
इस रूपांतरण को ऑब्जेक्ट के अंदर किया जा सकता है (उस के लिए ज्ञात आईएल निर्देशों का उपयोग करके), कस्टम रूपांतरण ऑपरेटरों (कास्ट करने के लिए वर्ग में परिभाषित) या अधिक जटिल तंत्र ( TypeConverterउदाहरण के लिए वर्ग या विधि) का उपयोग करके। आप इस बात से अवगत नहीं हैं कि ऐसा करने के लिए क्या होगा, लेकिन आप जानते हैं कि यह विफल हो सकता है (इसीलिए जब अधिक नियंत्रित रूपांतरण संभव हो तो IMO का उपयोग करना चाहिए)। आपके मामले में रूपांतरण केवल stringउत्पादन करने के लिए पार्स करेगा double:
double value = Double.Parse(aStringVariable);
बेशक यह विफल हो सकता है यदि आप ऐसा करते हैं तो आपको हमेशा उस अपवाद को पकड़ना चाहिए जो वह फेंक सकता है ( FormatException)। यह विषय से बाहर है लेकिन जब कोई TryParseउपलब्ध होता है तो आपको इसका उपयोग करना चाहिए (क्योंकि शब्दार्थ आप कहते हैं कि यह संख्या नहीं हो सकती है और यह और भी तेज़ है ... विफल होने के लिए)।
.NET में रूपांतरण बहुत से स्थानों से आ सकते हैं, TypeConverterउपयोगकर्ता परिभाषित रूपांतरण ऑपरेटरों के साथ अंतर्निहित / स्पष्ट जातियों, IConvertibleऔर लागू करने के तरीकों (क्या मैं कुछ भूल गया हूं?)। उनके बारे में अधिक जानकारी के लिए MSDN पर एक नज़र डालें।
इस लंबे उत्तर को समाप्त करने के लिए उपयोगकर्ता परिभाषित रूपांतरण ऑपरेटरों के बारे में कुछ शब्द। यह सिर्फ चीनी है जो प्रोग्रामर को एक प्रकार का दूसरे में बदलने के लिए एक कास्ट का उपयोग करने देता है। यह एक वर्ग के अंदर की एक विधि है (जो डाली जाएगी) जो कहती है कि "अरे, अगर वह इस प्रकार को उस प्रकार में बदलना चाहती है तो मैं ऐसा कर सकती हूं"। उदाहरण के लिए:
float? maybe = 10;
float sure1 = (float)maybe;
float sure2 = maybe.Value;
इस मामले में यह स्पष्ट है क्योंकि यह विफल हो सकता है लेकिन यह कार्यान्वयन के लिए है (भले ही इस बारे में दिशा-निर्देश हों)। कल्पना कीजिए कि आप इस तरह एक कस्टम स्ट्रिंग क्लास लिखते हैं:
EasyString text = "123";
double value = (string)text;
आपके कार्यान्वयन में आप "प्रोग्रामर के जीवन को आसान बनाने" और कलाकारों के माध्यम से इस रूपांतरण को उजागर करने का निर्णय ले सकते हैं (याद रखें कि यह सिर्फ एक शॉर्टकट है कम लिखने के लिए)। कुछ भाषा भी इसकी अनुमति दे सकती है:
double value = "123";
किसी भी प्रकार से अंतर्निहित रूपांतरण की अनुमति (चेक रन-टाइम पर किया जाएगा)। उचित विकल्पों के साथ यह किया जा सकता है, उदाहरण के लिए, VB.NET में। यह सिर्फ एक अलग दर्शन है।
मैं उनके साथ क्या कर सकता हूं?
तो अंतिम प्रश्न यह है कि आपको एक या दूसरे का उपयोग कब करना चाहिए। आइए देखें कि आप एक स्पष्ट कास्ट का उपयोग कब कर सकते हैं:
- आधार प्रकारों के बीच बातचीत।
- से आए रूपांतरण
objectकिसी भी अन्य प्रकार के लिए (यह भी unboxing शामिल हो सकते हैं)।
- एक व्युत्पन्न वर्ग से एक बेस क्लास (या एक कार्यान्वित इंटरफ़ेस) के लिए रूपांतरण।
- कस्टम रूपांतरण ऑपरेटरों के माध्यम से एक प्रकार से दूसरे प्रकार की बातचीत।
केवल पहला रूपांतरण आपके साथ Convertऐसा हो सकता है, जिसके लिए आपके पास कोई विकल्प नहीं है और आपको एक स्पष्ट कलाकार का उपयोग करने की आवश्यकता है।
आइए अब देखें कि आप कब उपयोग कर सकते हैं Convert:
- किसी भी आधार प्रकार से दूसरे आधार प्रकार के रूपांतरण (कुछ सीमाओं के साथ, MSDN देखें )।
- किसी भी प्रकार के रूपांतरण जो
IConvertibleकिसी अन्य (समर्थित) प्रकार पर लागू होते हैं।
byteस्ट्रिंग से / के लिए / से एक सरणी के लिए रूपांतरण ।
निष्कर्ष
IMO Convertका उपयोग हर बार किया जाना चाहिए जब आप जानते हैं कि रूपांतरण विफल हो सकता है (प्रारूप के कारण, सीमा के कारण या क्योंकि यह असमर्थित हो सकता है), भले ही वही रूपांतरण किसी कास्ट के साथ किया जा सकता है (जब तक कि कुछ और उपलब्ध न हो)। यह स्पष्ट करता है कि आपके कोड को कौन पढ़ेगा और आपका इरादा क्या है और यह विफल हो सकता है (डीबग को सरल बनाते हुए)।
बाकी सब के लिए आपको एक कास्ट का उपयोग करने की आवश्यकता है, कोई विकल्प नहीं है, लेकिन अगर एक और बेहतर तरीका उपलब्ध है, तो मेरा सुझाव है कि आप इसका उपयोग करें। अपने उदाहरण में से एक रूपांतरण stringकरने के लिए doubleकुछ है कि (पाठ उपयोगकर्ता से आता है, खासकर अगर) अक्सर एक का उपयोग कर उदाहरण के लिए असफल हो जायेगी तो आप ज्यादा स्पष्ट हो सके (इसके अलावा आप इसे पर अधिक नियंत्रण होता) के रूप में यह सुनिश्चित करना चाहिए, है TryParseविधि।
संपादित करें: उनके बीच क्या अंतर है?
अद्यतन प्रश्न के अनुसार और जो मैंने पहले लिखा था ( जब आप उपयोग कर सकते हैं / की तुलना में आप कास्ट का उपयोग कर सकते हैं के बारे में Convert) तब अंतिम बिंदु स्पष्ट करने के लिए है कि क्या उनके बीच अंतर है (इसके अलावा Convertउपयोग IConvertibleऔर IFormattableइंटरफेस इसलिए यह ऑपरेशन कर सकता है कलाकारों के साथ अनुमति नहीं है)।
संक्षिप्त उत्तर हाँ है, वे अलग तरह से व्यवहार करते हैं । मैं Convertक्लास को एक हेल्पर मेथड्स क्लास की तरह देखता हूं इसलिए अक्सर यह कुछ लाभ या थोड़ा अलग व्यवहार प्रदान करता है। उदाहरण के लिए:
double real = 1.6;
int castedInteger = (int)real;
int convertedInteger = Convert.ToInt32(real);
बहुत अलग है, है ना? कलाकारों ने छंटनी की (यह वही है जो हम सभी अपेक्षा करते हैं) लेकिन Convertनिकटतम पूर्णांक के लिए एक गोलाई प्रदर्शन करता है (और यदि आप इसके बारे में नहीं जानते हैं तो यह उम्मीद नहीं की जा सकती है)। प्रत्येक रूपांतरण पद्धति में अंतरों का परिचय दिया जाता है, इसलिए एक सामान्य नियम लागू नहीं किया जा सकता है और उन्हें मामले द्वारा देखा जाना चाहिए ... 19 आधार प्रकार हर दूसरे प्रकार में बदलने के लिए ... सूची बहुत लंबी हो सकती है, MSDN मामले से परामर्श करने के लिए बहुत बेहतर है मामला!