कास्टिंग से क्यों बचना चाहिए? [बन्द है]


97

मैं आमतौर पर जितना संभव हो उतना कास्टिंग प्रकार से बचता हूं क्योंकि मैं इस धारणा के तहत हूं कि यह खराब कोडिंग अभ्यास है और प्रदर्शन जुर्माना हो सकता है।

लेकिन अगर कोई मुझे यह बताने के लिए कहे कि वास्तव में ऐसा क्यों है, तो मैं शायद उन्हें हेडलाइट्स में एक हिरण की तरह देखूंगा।

तो क्यों / जब कास्टिंग खराब है?

क्या यह जावा, सी #, सी ++ के लिए सामान्य है या क्या हर अलग रनटाइम वातावरण इसके साथ अपनी शर्तों पर व्यवहार करता है?

किसी भी भाषा के लिए विशिष्टताओं का स्वागत है, उदाहरण है कि यह c ++ में खराब क्यों है?


3
आपको यह धारणा कहां से मिली?
Oded

8
मुझे यह आभास तब से हुआ, जब से मैंने कभी कोई पुस्तक नहीं पढ़ी या किसी प्रोग्रामर से नहीं मिला, जिसने कहा कि "CASTING SOOOO GOOOOD !!!"
लाउडएनपॉसिबल संभवतः

15
C ++ के लिए उत्तर C # के उत्तर से अनिवार्य रूप से भिन्न है। यह बहुत भाषा-विशिष्ट है। इस प्रकार उत्तर विशिष्ट भाषाओं के लिए इस प्रश्न का उत्तर देते हैं और कुछ मामलों में यह नहीं बताते हैं कि वे किस भाषा के बारे में बात कर रहे हैं।
जेम्स मैकनेलिस

2
बुरा एक सापेक्ष शब्द है। कास्टिंग से बचना सबसे अच्छा अभ्यास है, लेकिन कभी-कभी एक प्रोग्रामर को वह करना पड़ता है जो एक प्रोग्रामर को करने के लिए मिला है। (विशेष रूप से यदि आप एक जावा 1.5+ प्रोग्राम लिख रहे हैं जो 1.4 के लिए लिखी गई लाइब्रेरी का उपयोग करता है) तो शायद इस सवाल का नाम बदल दें, "हमें क्यों बचा जाना चाहिए?"
माइक मिलर

2
यह एक महान सवाल है .... यह 5 उपयोगकर्ताओं द्वारा बंद किया गया था, जिनमें से प्रत्येक की 10k से कम प्रतिष्ठा है !! स्पष्ट रूप से नई शक्तियों का अत्यधिक उपयोग। दोबारा खोलने के लिए मतदान किया है।
12:

जवाबों:


141

आपने इसे तीन भाषाओं के साथ टैग किया है, और उत्तर वास्तव में तीनों के बीच काफी भिन्न हैं। C ++ की चर्चा कमोबेश C जाति की चर्चा के रूप में अच्छी तरह से होती है, और यह चौथा उत्तर देता है (अधिक या कम)।

चूंकि यह वह है जिसका आपने स्पष्ट रूप से उल्लेख नहीं किया है, मैं सी। सी। के साथ शुरू करूँगा जिसमें कई समस्याएं हैं। एक यह है कि वे कई अलग-अलग चीजों में से कोई भी कर सकते हैं। कुछ मामलों में, कलाकार संकलक (संक्षेप में) को बताने से ज्यादा कुछ नहीं करता है: "चुप रहो, मुझे पता है कि मैं क्या कर रहा हूं" - यानी, यह सुनिश्चित करता है कि जब आप रूपांतरण करते हैं तो भी समस्या हो सकती है, संकलक आपको उन संभावित समस्याओं के बारे में चेतावनी नहीं देगा। बस उदाहरण के लिए, char a=(char)123456;। परिभाषित इस कार्यान्वयन का सटीक परिणाम (आकार और हस्ताक्षर पर निर्भर करता है)char), और बल्कि अजीब स्थितियों को छोड़कर, शायद उपयोगी नहीं है। सी कास्ट्स में भी भिन्नता है कि क्या वे कुछ हैं जो केवल संकलित समय पर होता है (यानी, आप केवल संकलक को बता रहे हैं कि कुछ डेटा की व्याख्या / उपचार कैसे करें) या कुछ ऐसा जो रन टाइम पर होता है (उदाहरण के लिए, डबल से वास्तविक रूपांतरण लंबा)।

C ++ "नए" कलाकारों के संचालकों को जोड़कर कम से कम कुछ हद तक इससे निपटने का प्रयास करता है, जिनमें से प्रत्येक केवल C कलाकारों की क्षमताओं के सबसेट तक सीमित है। इससे गलती से (उदाहरण के लिए) गलती से एक रूपांतरण हो जाता है जो आपने वास्तव में इरादा नहीं किया था - यदि आप केवल एक वस्तु पर कब्ज दूर करने का इरादा रखते हैं, तो आप उपयोग कर सकते हैं const_cast, और सुनिश्चित करें कि केवल एक चीज जो इसे प्रभावित कर सकती है, वह है एक वस्तु है const, volatileया नहीं। इसके विपरीत, एक static_castको प्रभावित करने की अनुमति नहीं है कि कोई वस्तु है constया नहींvolatile। संक्षेप में, आपके पास अधिकांश एक ही प्रकार की क्षमताएं हैं, लेकिन उन्हें वर्गीकृत किया जाता है ताकि एक कलाकार आम तौर पर केवल एक ही प्रकार का रूपांतरण कर सके, जहां एक एकल सी-स्टाइल कास्ट एक ऑपरेशन में दो या तीन रूपांतरण कर सकता है। प्राथमिक अपवाद यह है कि आप कम से कम कुछ मामलों में ए की जगह का उपयोग कर सकते हैं और एक के रूप में लिखे जाने के बावजूद , यह वास्तव में ए के रूप में समाप्त हो जाएगा । उदाहरण के लिए, आप किसी वर्ग पदानुक्रम को आगे या पीछे करने के लिए उपयोग कर सकते हैं - लेकिन एक कास्ट "अप" पदानुक्रम हमेशा सुरक्षित होता है, इसलिए इसे स्टैटिकली किया जा सकता है, जबकि एक कास्ट "डाउन" पदानुक्रम जरूरी नहीं है इसलिए यह आवश्यक नहीं है गतिशील रूप से किया।dynamic_caststatic_castdynamic_caststatic_castdynamic_cast

जावा और C # एक दूसरे के समान हैं। विशेष रूप से, उन दोनों के साथ कास्टिंग (वस्तुतः?) हमेशा एक रन-टाइम ऑपरेशन है। C ++ के कास्ट ऑपरेटर्स के संदर्भ में, यह आमतौर पर एक dynamic_castचीज़ के संदर्भ में सबसे नज़दीकी होता है - जो कि, जब आप किसी लक्ष्य प्रकार के ऑब्जेक्ट को डालने का प्रयास करते हैं, तो कंपाइलर रन-टाइम चेक को यह देखने के लिए सम्मिलित करता है कि क्या रूपांतरण की अनुमति है , और एक अपवाद फेंक दो अगर यह नहीं है। सटीक विवरण (उदाहरण के लिए, "खराब कास्ट" अपवाद के लिए उपयोग किया जाने वाला नाम) भिन्न होता है, लेकिन मूल सिद्धांत ज्यादातर समान रहता है (हालांकि, यदि स्मृति कार्य करती है, तो जावा कुछ गैर-ऑब्जेक्ट प्रकारों पर लागू होता है जैसे intसी के बहुत करीब। कास्ट्स - लेकिन इन प्रकारों का उपयोग शायद ही कभी किया जाता है 1) मुझे यह याद नहीं है कि यकीन है, और 2) भले ही यह सच है, यह वैसे भी बहुत मायने नहीं रखता है)।

चीजों को आम तौर पर देखते हुए, स्थिति बहुत सरल है (कम से कम आईएमओ): एक कास्ट (स्पष्ट रूप से पर्याप्त) का मतलब है कि आप कुछ को एक प्रकार से दूसरे में परिवर्तित कर रहे हैं। जब / यदि आप ऐसा करते हैं, तो यह सवाल उठता है कि "क्यों?" यदि आप वास्तव में एक विशेष प्रकार के लिए कुछ चाहते हैं, तो आपने इसे उस प्रकार से परिभाषित क्यों नहीं किया है जिसके साथ शुरू करना है? यह कहना नहीं है कि इस तरह के रूपांतरण को करने का कोई कारण नहीं है, लेकिन कभी भी ऐसा होता है, तो यह इस सवाल का संकेत देना चाहिए कि क्या आप कोड को फिर से डिज़ाइन कर सकते हैं, इसलिए सही प्रकार का उपयोग किया गया था। यहां तक ​​कि सहज रूप से अंतरंग रूपांतरण (जैसे, पूर्णांक और फ्लोटिंग बिंदु के बीच) की तुलना में सामान्य रूप से बहुत अधिक बारीकी से जांच की जानी चाहिए। उनके लगने के बावजूदसमानता, पूर्णांक वास्तव में चीजों की "गणना" प्रकार और "मापा" प्रकार की चीजों के लिए फ्लोटिंग बिंदु के लिए उपयोग किया जाना चाहिए। भेद को नजरअंदाज करना कुछ पागल बयानों की ओर जाता है जैसे "औसत अमेरिकी परिवार में 1.8 बच्चे हैं।" भले ही हम सभी देख सकते हैं कि यह कैसे होता है, तथ्य यह है कि किसी भी परिवार में 1.8 बच्चे नहीं हैं। उनके पास 1 हो सकता है या वे 2 हो सकते हैं या उनके पास इससे अधिक हो सकता है - लेकिन 1.8 कभी नहीं।


10
ऐसा लगता है कि आप 'ध्यान अवधि द्वारा मौत' पीड़ित हैं, यह एक अच्छा जवाब है।
स्टीव टाउनसेंड

2
एक मजबूत जवाब, लेकिन "मुझे नहीं पता" भागों में से कुछ इसे व्यापक बनाने के लिए कड़ा किया जा सकता है। @ Dragontamer5788 यह एक अच्छा जवाब है, लेकिन व्यापक नहीं है।
एम

5
एक पूरा बच्चा और एक बच्चा गायब पैर के साथ 1.8 बच्चे होंगे। लेकिन बहुत अच्छा जवाब कोई भी कम नहीं है। :)
ओज़।

1
बिना बच्चों वाले जोड़ों को छोड़कर कम से कम एक बहुत अच्छा जवाब बाधा नहीं है

@रोगर: छोड़कर नहीं, सिर्फ अनदेखी।
जेरी कॉफिन

48

यहाँ बहुत अच्छे जवाब। यहाँ मैं इसे जिस तरह से देख रहा हूं (एक सी # परिप्रेक्ष्य से)।

आमतौर पर कास्टिंग का मतलब दो चीजों में से एक है:

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

  • संकलक और डेवलपर दोनों ही अभिव्यक्ति के रनटाइम प्रकार को जानते हैं। मूल्य के साथ जुड़े एक अलग प्रकार का एक और मूल्य है जो इस अभिव्यक्ति के क्रम में होगा। उत्पन्न कोड जो दिए गए प्रकार के मूल्य से वांछित प्रकार के मूल्य का उत्पादन करता है; यदि आप ऐसा नहीं कर सकते, तो एक अपवाद फेंक दें।

गौर करें कि वे विरोधी हैं । जाति दो प्रकार की होती है! ऐसी जातियाँ हैं जहाँ आप वास्तविकता के बारे में संकलक को संकेत दे रहे हैं - अरे, प्रकार की वस्तु की यह बात वास्तव में प्रकार के ग्राहक की है - और ऐसी जातियाँ हैं जहाँ आप संकलक को एक प्रकार से दूसरे प्रकार की मैपिंग करने के लिए कह रहे हैं - अरे मुझे इस डबल से मेल खाने वाले इंट की जरूरत है।

दोनों तरह की जातियां लाल झंडे हैं। पहली तरह की कास्ट सवाल उठाती है "वास्तव में ऐसा क्यों है कि डेवलपर कुछ जानता है जो कंपाइलर नहीं करता है?" आप उस स्थिति में कर रहे हैं तो ऐसा करने के लिए बेहतर बात कार्यक्रम बदलने के लिए इतना है कि संकलक आमतौर पर है करता है वास्तविकता पर एक संभाल। फिर आपको कलाकारों की ज़रूरत नहीं है; विश्लेषण संकलन समय पर किया जाता है।

दूसरी तरह की कास्ट सवाल उठाती है "पहली बार में लक्ष्य डेटा प्रकार में ऑपरेशन क्यों नहीं किया जा रहा है?" यदि आपको किलों में परिणाम की आवश्यकता है तो आप पहले स्थान पर एक डबल क्यों धारण कर रहे हैं? क्या आपको एक इंट धारण नहीं करना चाहिए?

यहाँ कुछ अतिरिक्त विचार:

http://blogs.msdn.com/b/ericlippert/archive/tags/cast+operator/


2
मुझे नहीं लगता कि वे स्वाभाविक रूप से लाल झंडे हैं। यदि आपके पास कोई ऐसी Fooवस्तु है, जो आपको विरासत में मिली है Bar, और आप उस में स्टोर करते हैं List<Bar>, तो अगर आपको वह Fooवापस चाहिए तो आपको कास्ट की आवश्यकता होगी । शायद यह एक वास्तुशिल्प स्तर पर एक समस्या को इंगित करता है (हम Barएस के बजाय एस क्यों स्टोर कर रहे हैं Foo?), लेकिन जरूरी नहीं। और, अगर उस के पास Fooभी एक वैध कास्ट है int, तो यह आपकी अन्य टिप्पणी से भी संबंधित है: आप ए स्टोर कर रहे हैं Foo, ए नहीं int, क्योंकि intयह हमेशा उचित नहीं है।
माइक कैरन

6
@ माइक कैरन - मैं एरिक के लिए जवाब नहीं दे सकता, जाहिर है, लेकिन मेरे लिए एक लाल झंडा का मतलब है "यह सोचने के लिए कुछ है", न कि "यह कुछ गलत है"। और ए Fooमें स्टोर करने में कोई परेशानी नहीं है List<Bar>, लेकिन आप जिस कलाकार के साथ कुछ करने की कोशिश कर रहे हैं, उस बिंदु पर Fooयह उचित नहीं है Bar। इसका मतलब है कि उपप्रकारों के लिए अलग-अलग व्यवहार आभासी तरीकों द्वारा प्रदान किए गए अंतर्निहित बहुरूपता के अलावा एक तंत्र के माध्यम से किया जा रहा है। शायद यह सही समाधान है, लेकिन अधिक बार यह एक लाल झंडा है।
जेफरी एल व्हाइटजेल

14
वास्तव में। यदि आप जानवरों की सूची से सामान निकाल रहे हैं और आपको बाद में संकलक को बताने की आवश्यकता है, तो ओह, वैसे, मुझे पता है कि पहला एक बाघ है, दूसरा एक शेर है, और तीसरा एक एक भालू है, तो आपको एक Tuple <शेर, बाघ, भालू> का उपयोग करना चाहिए था, सूची <पशु> नहीं।
एरिक लिपपार्ट

5
मैं आपसे सहमत हूं, लेकिन मुझे लगता है कि Tuple<X,Y,...>ट्यूपल्स के लिए बेहतर सिंटैक्टिक समर्थन के बिना C # में व्यापक उपयोग की संभावना नहीं है। यह एक ऐसी जगह है जहाँ भाषा लोगों को "सफलता के गड्ढे" की ओर धकेलने का बेहतर काम कर सकती है।
kvb

4
@kvb: मैं सहमत हूं। हमने C # 4 के लिए एक ट्यूल सिंटैक्स अपनाने पर विचार किया लेकिन यह बजट में फिट नहीं हुआ। शायद सी # 5 में; हमने अभी तक पूर्ण सुविधा सेट पर काम नहीं किया है। CST को Async के लिए एक साथ लाने में बहुत व्यस्त। या शायद एक काल्पनिक भविष्य के संस्करण में।
एरिक लिपर्ट

36

कास्टिंग त्रुटियों को हमेशा जावा में रन-टाइम त्रुटियों के रूप में रिपोर्ट किया जाता है। जेनरिक या टेम्प्लेटिंग का उपयोग इन त्रुटियों को संकलन-समय की त्रुटियों में बदल देता है, जिससे यह पता लगाना बहुत आसान हो जाता है कि आपने कब गलती की है।

जैसा कि मैंने ऊपर कहा। यह कहना नहीं है कि सभी कास्टिंग खराब हैं। लेकिन अगर इससे बचना संभव है, तो ऐसा करना सबसे अच्छा है।


4
यह मानता है कि सभी कास्टिंग "खराब" हैं; हालाँकि, यह पूरी तरह सच नहीं है। उदाहरण के लिए C # लें, दोनों निहित और स्पष्ट कलाकारों के समर्थन के साथ। समस्या तब आती है जब एक कलाकार किया जाता है जो (गलती से) जानकारी या प्रकार-सुरक्षा को हटा देता है (यह भाषा द्वारा भिन्न होता है)।

5
दरअसल, यह C ++ में गलत है। शायद इस जानकारी के साथ लक्षित भाषा (भाषाओं) को शामिल करने के लिए एक संपादन क्रम में है।
स्टीव टाउनसेंड

@ एरिक - मैं करूँगा, लेकिन मुझे जावा के बारे में पहली बात नहीं पता, और न ही पर्याप्त सी # जानकारी सुनिश्चित करने के लिए कि जानकारी सही है।
स्टीव टाउनसेंड

क्षमा करें, मैं एक जावा लड़का हूं, इसलिए मेरा सी ++ ज्ञान काफी सीमित है। मैं इसमें से "टेंपलेटिंग" शब्द को संपादित कर सकता था, जैसा कि अस्पष्ट होने का इरादा था।
माइक मिलर

ऐसा नहीं। कुछ कास्ट एरर्स जावा कंपाइलर द्वारा पकड़े जाते हैं, न कि केवल सामान्य वाले। विचार करें (स्ट्रिंग) 0;
लोर्ने

18

कास्टिंग स्वाभाविक रूप से बुरा नहीं है, यह सिर्फ इतना है कि इसे अक्सर कुछ हासिल करने के साधन के रूप में दुरुपयोग किया जाता है जो वास्तव में या तो बिल्कुल नहीं किया जाना चाहिए, या अधिक सुरुचिपूर्ण ढंग से किया जाना चाहिए।

यदि यह सार्वभौमिक रूप से खराब होता, तो भाषाएं इसका समर्थन नहीं करतीं। किसी भी अन्य भाषा विशेषता की तरह, इसका स्थान है।

मेरी सलाह होगी कि आप अपनी प्राथमिक भाषा पर ध्यान दें, और इसकी सभी जातियों और इससे जुड़ी सर्वोत्तम प्रथाओं को समझें। भ्रमण को अन्य भाषाओं में सूचित करना चाहिए।

प्रासंगिक C # डॉक्स यहां हैं

यहां पिछले SO प्रश्न पर C ++ विकल्पों पर एक बहुत अच्छा सारांश है


9

मैं यहाँ ज्यादातर C ++ के लिए बोल रहा हूँ , लेकिन यह सबसे अधिक जावा और C # पर लागू होता है:

C ++ एक स्टेटिकली टाइप्ड भाषा है । कुछ लीवेज़ हैं भाषा आपको इस (वर्चुअल फ़ंक्शंस, निहितार्थ रूपांतरण) में अनुमति देती है, लेकिन मूल रूप से संकलक को संकलन-समय पर हर वस्तु का प्रकार पता है। ऐसी भाषा का उपयोग करने का कारण यह है कि संकलन-समय पर त्रुटियों को पकड़ा जा सकता है । यदि कंपाइलर के प्रकारों को जानता है aऔर b, तो यह आपको कंपाइल-टाइम पर पकड़ लेगा जब आप ऐसा करेंगे a=bजहां aएक जटिल संख्या है और bएक स्ट्रिंग है।

जब भी आप स्पष्ट कास्टिंग करते हैं तो आप कंपाइलर को बंद करने के लिए कहते हैं, क्योंकि आपको लगता है कि आप बेहतर जानते हैं । यदि आप गलत हैं, तो आप आमतौर पर केवल रन-टाइम पर पता करेंगे । और रन-टाइम पर पता लगाने के साथ समस्या यह है कि यह एक ग्राहक पर हो सकता है।


5

जावा, c # और c ++ दृढ़ता से टाइप की जाने वाली भाषाएं हैं, हालांकि दृढ़ता से टाइप की जाने वाली भाषाओं को अनम्य के रूप में देखा जा सकता है, उन्हें संकलन समय पर टाइप चेकिंग करने और कुछ कार्यों के लिए गलत प्रकार के कारण होने वाली रनटाइम त्रुटियों से बचाने का लाभ है।

दो प्रकार की जातियाँ होती हैं: एक सामान्य से अधिक प्रकार की या दूसरी प्रकार की जाति (अधिक विशिष्ट)। अधिक सामान्य प्रकार (एक माता-पिता के लिए कास्टिंग) के लिए कास्टिंग संकलित समय के चेक को बरकरार रखेगा। लेकिन अन्य प्रकार (अधिक विशिष्ट प्रकार) में कास्टिंग संकलन समय प्रकार की जांच को अक्षम कर देगा और संकलक द्वारा एक रनटाइम चेक द्वारा प्रतिस्थापित किया जाएगा। इसका मतलब है कि आपके पास कम निश्चितता है आप संकलित कोड सही ढंग से चलेंगे। अतिरिक्त रनटाइम प्रकार की जांच (जावा एपीआई कलाकारों से भरा हुआ है) के कारण इसका कुछ नगण्य प्रदर्शन प्रभाव पड़ता है।


5
C ++ में सभी कलाकार "बायपास" प्रकार की सुरक्षा नहीं करते हैं।
जेम्स मैकनेलिस

4
सभी जाति "बाईपास" प्रकार की सुरक्षा C # में नहीं है।

5
सभी कलाकार जावा में "बायपास" प्रकार की सुरक्षा नहीं करते हैं।
एलिक रॉबर्टसन

11
सभी कास्टिंग में "बायपास" प्रकार की सुरक्षा नहीं है। ओह रुको, उस टैग में एक भाषा का उल्लेख नहीं है ...
sbi

2
C # और Java में लगभग सभी मामलों में, कास्टिंग आपको एक प्रदर्शन में गिरावट देगा, क्योंकि सिस्टम रन-टाइम प्रकार की जाँच करेगा (जो मुफ़्त नहीं है)। C ++ में, dynamic_castआमतौर पर की तुलना में धीमी होती है static_cast, क्योंकि इसमें आम तौर पर रन-टाइम टाइप चेकिंग (कुछ कैविट्स के साथ: बेस टाइप के लिए कास्टिंग करना सस्ता होता है, आदि) होता है।
ट्रैविस गोकेल

4

कुछ प्रकार के कास्टिंग इतने सुरक्षित और कुशल होते हैं कि अक्सर उन्हें कास्टिंग भी नहीं माना जाता है।

यदि आप एक व्युत्पन्न प्रकार से आधार प्रकार के लिए जाते हैं, तो यह आम तौर पर काफी सस्ता होता है (अक्सर - भाषा, कार्यान्वयन और अन्य कारकों के आधार पर - यह शून्य-लागत है) और सुरक्षित है।

यदि आप एक साधारण प्रकार से एक इंट की तरह एक व्यापक प्रकार से एक लंबे इंट की तरह कास्ट करते हैं, तो फिर से यह अक्सर काफी सस्ता होता है (आमतौर पर उसी प्रकार के असाइन करने की तुलना में बहुत अधिक महंगा नहीं होता जितना कि) और फिर सुरक्षित है।

अन्य प्रकार अधिक घातक और / या अधिक महंगे हैं। अधिकांश भाषाओं में आधार प्रकार से व्युत्पन्न प्रकार तक की ढलाई या तो सस्ती होती है, लेकिन इसमें गंभीर त्रुटि का उच्च जोखिम होता है (C ++ में यदि आप आधार से स्थैतिक_कास्ट प्राप्त करते हैं तो यह सस्ता होगा, लेकिन यदि अंतर्निहित मान व्युत्पन्न प्रकार का नहीं है व्यवहार अपरिभाषित है और बहुत अजीब हो सकता है) या अपेक्षाकृत महंगा है और एक अपवाद को बढ़ाने के जोखिम के साथ (C ++ में डायनामिक_कास्ट, सी # में स्पष्ट आधार-से-व्युत्पन्न कास्ट, और इसी तरह)। जावा और सी # में बॉक्सिंग इसका एक और उदाहरण है, और इससे भी अधिक खर्च (यह मानते हुए कि वे अंतर्निहित मानों का इलाज कैसे किया जाता है) की तुलना में अधिक बदल रहे हैं।

अन्य प्रकार के कलाकार जानकारी खो सकते हैं (एक पूर्णांक प्रकार से एक छोटा पूर्णांक प्रकार)।

जोखिम के ये मामले (चाहे अपवाद हो या अधिक गंभीर त्रुटि) और खर्च के सभी कारण कास्टिंग से बचने के लिए हैं।

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

अंत में, कलाकारों का भारी उपयोग वस्तु मॉडल पर विचार करने में विफलता का संकेत दे सकता है या तो इसे बनाने में, इसका उपयोग करते हुए, या दोनों: एक ही प्रकार के बीच बार-बार कास्टिंग करना लगभग हमेशा प्रकारों के बीच संबंधों पर विचार करने में विफलता है। उपयोग किया गया। यहाँ यह इतना नहीं है कि जातियाँ बुरी हैं, क्योंकि वे किसी चीज़ के खराब होने का संकेत हैं।


2

भाषा सुविधाओं ("कभी भी XXX का उपयोग न करें", "XXX को हानिकारक माना जाता है" आदि) के उपयोग के बारे में प्रोग्रामर के लिए कुत्तों के नियमों से चिपके रहने की प्रवृत्ति बढ़ रही है, जहां XXX में बिंदुओं से gotoलेकर protectedडेटा सदस्यों के सिंगनलन से लेकर पासिंग ऑब्जेक्ट तक हैं। मूल्य।

इस तरह के नियमों का पालन करना, मेरे अनुभव में, दो चीजों को सुनिश्चित करता है: आप एक भयानक प्रोग्रामर नहीं होंगे, न ही आप एक शानदार प्रोग्रामर होंगे।

एक बेहतर तरीका यह है कि इन कंबल निषेधों के पीछे सच्चाई की गिरी को खोदें और उजागर करें, और फिर समझदारी के साथ सुविधाओं का उपयोग करें। कर रहे हैं कई स्थितियों जिसके लिए वे काम के लिए सबसे अच्छा उपकरण कर रहे हैं।

"मैं आमतौर पर जितना संभव हो उतना कास्टिंग प्रकारों से बचता हूं" इस तरह के अतिरंजित नियम का एक अच्छा उदाहरण है। कई सामान्य स्थितियों में जातियाँ आवश्यक हैं। कुछ उदाहरण:

  1. जब थर्ड-पार्टी कोड के साथ इंटरऑपरेटिंग (विशेषकर जब वह कोड typedefs के साथ व्याप्त हो )। (उदाहरण: GLfloat<->double <->Real )
  2. व्युत्पन्न से बेस क्लास पॉइंटर / संदर्भ तक कास्टिंग: यह इतना सामान्य और प्राकृतिक है कि संकलक इसे अंतर्निहित रूप से करेगा। यदि यह स्पष्ट रूप से पठनीयता बढ़ाता है, तो कास्ट एक कदम आगे है, न कि पीछे की ओर!
  3. आधार से व्युत्पन्न वर्ग सूचक / संदर्भ के लिए कास्टिंग: सामान्य रूप से, यहां तक ​​कि अच्छी तरह से डिज़ाइन किए गए कोड में भी। (उदाहरण: विषम कंटेनर।)
  4. बाइनरी क्रमांकन / डिसेरिएलाइज़ेशन या अन्य निम्न-स्तरीय कोड के अंदर जो अंतर्निहित प्रकारों के कच्चे बाइट्स तक पहुंच की आवश्यकता होती है।
  5. किसी भी समय जब यह एक अलग प्रकार का उपयोग करने के लिए सिर्फ सादा अधिक प्राकृतिक, सुविधाजनक और पठनीय है। (उदाहरण: std::size_type-> int)

निश्चित रूप से ऐसी कई स्थितियाँ हैं जहाँ किसी कलाकार का उपयोग करना उचित नहीं है, और इनको सीखना भी महत्वपूर्ण है; मैं बहुत अधिक विस्तार में नहीं जाऊंगा क्योंकि ऊपर दिए गए जवाबों ने उनमें से कुछ को इंगित करते हुए एक अच्छा काम किया है।


1

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

C # के लिए विशिष्ट संबंध के साथ, क्योंकि इसमें ऑपरेटर isऔर asऑपरेटर शामिल हैं, आपके पास (अधिकांश भाग के लिए) यह निर्धारित करने का अवसर है कि कोई कलाकार सफल होगा या नहीं। इस वजह से, आपको यह निर्धारित करने के लिए उचित कदम उठाना चाहिए कि क्या ऑपरेशन सफल होगा या उचित रूप से आगे बढ़ेगा।


1

C # के मामले में, किसी को बॉक्सिंग / अनबॉक्सिंग ओवरहेड्स की वजह से कास्टिंग करते समय अधिक सावधानी बरतने की आवश्यकता है, जबकि मूल्य प्रकारों के साथ काम करना।


1

यह निश्चित नहीं है कि किसी ने पहले से ही इसका उल्लेख किया है, लेकिन सी # कास्टिंग में एक सुरक्षित तरीके से इस्तेमाल किया जा सकता है, और अक्सर आवश्यक होता है। मान लीजिए कि आपको एक वस्तु मिलती है, जो कई प्रकार की हो सकती है। isकीवर्ड का उपयोग करके आप पहले यह पुष्टि कर सकते हैं कि ऑब्जेक्ट वास्तव में उस प्रकार का है जिसे आप इसे डालने वाले हैं, और फिर ऑब्जेक्ट को सीधे उस प्रकार पर कास्ट करें। (मैंने जावा के साथ बहुत काम नहीं किया, लेकिन मुझे यकीन है कि वहाँ ऐसा करने का बहुत सीधा तरीका है)।


1

यदि आप 2 शर्तों को पूरा करते हैं, तो आप केवल किसी प्रकार के लिए एक वस्तु डालते हैं:

  1. आप जानते हैं कि यह उस प्रकार का है
  2. संकलक नहीं करता है

इसका मतलब यह नहीं है कि आपके पास मौजूद सभी जानकारी आपके द्वारा उपयोग की जाने वाली संरचना में अच्छी तरह से दर्शाई गई है। यह बुरा है, क्योंकि आपका कार्यान्वयन शब्दार्थ होना चाहिए में आपके मॉडल का , जो इस मामले में स्पष्ट रूप से नहीं है।

अब जब आप एक कास्ट करते हैं, तो इसके 2 अलग-अलग कारण हो सकते हैं:

  1. आपने टाइप संबंधों को व्यक्त करने में बुरा काम किया।
  2. भाषा प्रकार प्रणाली बस उन्हें वाक्यांश के लिए पर्याप्त अभिव्यंजक नहीं है।

अधिकांश भाषाओं में आप दूसरी स्थिति में बहुत बार चलते हैं। जावा में जेनेरिक थोड़ी मदद करते हैं, सी ++ टेम्पलेट सिस्टम और भी अधिक, लेकिन यह मास्टर करना मुश्किल है और फिर भी कुछ चीजें असंभव हो सकती हैं या बस प्रयास के लायक नहीं हैं।

तो आप कह सकते हैं, कुछ विशिष्ट भाषा में कुछ विशिष्ट प्रकार के संबंधों को व्यक्त करने के लिए आपकी समस्याओं को दरकिनार करने के लिए एक कलाकार एक गंदा हैक है। डर्टी हैक्स से बचना चाहिए। लेकिन आप उनके बिना कभी नहीं रह सकते।


0

आम तौर पर टेम्पलेट (या जेनरिक) कलाकारों की तुलना में अधिक सुरक्षित होते हैं। उस संबंध में, मैं कहूंगा कि कास्टिंग के साथ एक मुद्दा टाइप-सेफ्टी है। हालांकि, विशेष रूप से डाउनकास्टिंग: डिजाइन के साथ एक और अधिक सूक्ष्म मुद्दा जुड़ा हुआ है। मेरे दृष्टिकोण से कम से कम, डाउनकास्टिंग एक कोड गंध है, एक संकेत है कि मेरी इच्छा के साथ कुछ गलत हो सकता है और मुझे आगे की जांच करनी चाहिए। क्यों सरल है: यदि आप "सही" सार प्राप्त करते हैं, तो आपको इसकी आवश्यकता नहीं है! वैसे अच्छा सवाल है ...

चीयर्स!


0

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

(मैं स्पष्ट रूप से स्वतंत्र बाइटकोड और आईएल वास्तुकला की अनदेखी कर रहा हूं।)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.