C # में जादू के तरीके क्यों लागू किए गए?


16

C # में, मैंने इन सभी जादू के तरीकों को पॉप अप करते हुए देखना शुरू कर दिया, बिना किसी इंटरफ़ेस के बैकअप के। इसे क्यों चुना गया?

मुझे समझाने दो।

पहले C # में, यदि कोई ऑब्जेक्ट IEnumerableइंटरफ़ेस को लागू करता है, तो यह स्वचालित रूप से एक foreachलूप द्वारा चलने योग्य होगा । यह मेरे लिए समझ में आता है, क्योंकि यह एक इंटरफ़ेस द्वारा समर्थित है, और अगर मुझे Iteratorकक्षा के अंदर अपना कार्य करना होता है, तो मैं यह चिंता किए बिना कर सकता हूं कि यह जादुई रूप से कुछ और होगा।

अब, स्पष्ट रूप से, (निश्चित नहीं है कि कब), इन इंटरफेस की अब आवश्यकता नहीं है। इसके लिए बस सही नामकरण रूपांतरण होना चाहिए।

एक अन्य उदाहरण किसी भी वस्तु को उचित नाम दे कर प्रतीक्षा योग्य बना रहा है GetAwaiter जिसमें कुछ विशिष्ट गुण हैं।

क्यों एक अंतरफलक नहीं की तरह वे के साथ किया था IEnumerableया INotifyPropertyChangedस्थिर इस "जादू" बैकअप लेने के लिए?

मैं यहाँ क्या मतलब पर अधिक जानकारी:

http://blog.nem.ec/2014/01/01/magic-methods-c-sharp/

मैजिक मेथड्स के पेशेवरों और विपक्ष क्या हैं, और क्या कहीं भी ऑनलाइन है जहां मुझे कुछ भी पता चल सकता है कि ये फैसले क्यों किए गए थे?


4
यदि आप बंद नहीं करना चाहते हैं तो आपको अपनी व्यक्तिगत राय को "जादू बुरा है" क्यों संपादित करना चाहिए।
डगएम

2
यदि आप जानना चाहते हैं कि एंडर्स हेजलबर्ग ने ऐसा क्यों किया, तो आपको उससे पूछना पड़ेगा। मैं केवल आपको बता सकता हूं कि मैंने ऐसा क्यों किया होगा, और यह फॉरवर्ड-संगतता के लिए है। एक्सटेंशन विधियाँ आपको मौजूदा प्रकार के तरीकों को जोड़ने के लिए "नकली" करने की अनुमति देती हैं, लेकिन कोई एक्सटेंशन इंटरफेस नहीं हैं। यदि आपको async/ के लिए एक इंटरफ़ेस की आवश्यकता है, / await, तो वह केवल उस कोड के साथ काम करेगा, जो .NET 4.5 के बाद लिखा गया था, जो एक व्यवहार्य लक्ष्य होने के लिए पर्याप्त विस्तृत हो गया ... जो मूल रूप से अब है। लेकिन विधि कॉल में एक विशुद्ध रूप से वाक्यविन्यास अनुवाद मुझे awaitतथ्य के बाद मौजूदा प्रकारों में कार्यक्षमता जोड़ने की अनुमति देता है।
जोर्ज डब्ल्यू मित्तग

2
ध्यान दें कि यह मूल रूप से ऑब्जेक्ट-ओरिएंटेशन लागू होता है: जब तक कोई ऑब्जेक्ट उपयुक्त संदेशों का जवाब देता है, तब तक इसे सही प्रकार का माना जाता है।
जोर्ग डब्ल्यू मित्तग

7
आपका "पहले" और "अब" पिछड़ा हुआ है - जादू की विधि को foreachशुरुआत में एक पाश के लिए आधार कार्यक्षमता के रूप में लागू किया गया था । वहाँ कभी नहीं वस्तु को लागू करने के लिए एक आवश्यकता किया गया है IEnumerableके लिए foreachकाम करने के लिए। यह सिर्फ ऐसा करने के लिए सम्मेलन है।
जेसी सी। स्लाइसर

2
@gbulmer यह वह जगह है जहाँ से मुझे यह विचार याद आ रहा है: blogs.msdn.com/b/ericlippert/archive/2011/06/30/… (और कुछ हद तक ericlippert.com/2013/07/22/… )
जेसी सी। स्लीकर

जवाबों:


16

सामान्य तौर पर "मैजिक मेथड्स" का उपयोग तब किया जाता है, जब ऐसा इंटरफ़ेस बनाना संभव न हो जो उसी तरह काम करे।

जब foreachपहली बार C # 1.0 में पेश किया गया था (यह व्यवहार निश्चित रूप से हाल ही में कुछ भी नहीं है), इसे जादू के तरीकों का उपयोग करना था, क्योंकि कोई जेनरिक नहीं थे। मूल रूप से विकल्प थे:

  1. गैर-जेनेरिक का उपयोग करें IEnumerableऔर IEnumeratorयह objectएस के साथ काम करता है , जिसका अर्थ है बॉक्सिंग मूल्य प्रकार। चूँकि ints की सूची जैसी किसी चीज़ की पुनरावृति बहुत तेज़ होनी चाहिए और निश्चित रूप से बहुत सारे कचरा बॉक्स वाले मूल्यों को नहीं बनाना चाहिए, यह एक अच्छा विकल्प नहीं है।

  2. जेनरिक की प्रतीक्षा करें। यह संभवतः foreach3 साल से अधिक देरी से .net 1.0 (या कम से कम ) का मतलब होगा ।

  3. जादू के तरीकों का उपयोग करें।

इसलिए, उन्होंने # 3 विकल्प चुना और यह हमारे साथ पीछे की ओर संगतता कारणों से बना रहा, भले ही .Net 2.0 के बाद से, आवश्यकता होती IEnumerable<T>है।


संग्रह आरंभीकरण प्रत्येक संग्रह प्रकार पर अलग दिख सकता है। तुलना करें List<T>:

public void Add(T item)

और Dictionary<TKey, TValue>:

public void Add(TKey key, TValue value)

आपके पास एक भी इंटरफ़ेस नहीं हो सकता है जो केवल पहले फॉर्म के लिए List<T>और केवल दूसरे के लिए समर्थन करेगा Dictionary<TKey, TValue>


LINQ मेथड्स को आमतौर पर एक्सटेंशन मेथड्स के रूप में कार्यान्वित किया जाता है (ताकि सभी प्रकारों को लागू करने के लिए उदाहरण के लिए LINQ का एक ही इम्प्लीमेंटेशन हो सके IEnumerable<T>), जिसका अर्थ है कि इंटरफ़ेस का उपयोग करना संभव नहीं है।


के लिए await, GetResult()विधि voidया तो वापस आ सकती है या कुछ प्रकार T। फिर, आपके पास एक भी इंटरफ़ेस नहीं है जो दोनों को संभाल सकता है। हालांकि awaitआंशिक रूप से इंटरफ़ेस-आधारित है: वेटर को लागू करना है INotifyCompletionऔर यह भी लागू कर सकता है ICriticalNotifyCompletion


1
क्या आप निश्चित हैं "उन्होंने C # 1.0 के लिए # 3 विकल्प चुना"? मेरा स्मरण है यह विकल्प 1 था। मेरी स्मृति है, C # ने जावा पर महत्वपूर्ण श्रेष्ठता का दावा किया क्योंकि C # संकलक ने 'ऑटो-बॉक्सिंग' और 'ऑटो-अनबॉक्सिंग' किया। यह दावा किया गया था, कि C # बनाया गया कोड उस वजह से जावा की तुलना में बहुत बेहतर है।
22

1
foreachC # 1.2 के लिए दस्तावेज़ीकरण (C # 1.0 के लिए MSDN पर कुछ भी नहीं है) कहता है कि foreach"एक प्रकार को लागू करने वाले IEnumerableया एक प्रकार की GetEnumeratorविधि की घोषणा करने वाले" के रूप में अभिव्यक्ति का अर्थ है। और मुझे यकीन नहीं है कि आप इसका क्या अर्थ रखते हैं। C # में हमेशा स्पष्ट है।
svick

1
दिसंबर 2001 से Cg के लिए @gbulmer और ECMA विनिर्देश (जिसका अर्थ है कि यह C # 1.0 के लिए है) यह भी कहता है कि (that15.8.4): "एक प्रकार C को एक संग्रह प्रकार कहा जाता है यदि यह System .IEnumerable इंटरफ़ेस को लागू करता है या निम्नलिखित सभी मानदंडों को पूरा करके संग्रह पैटर्न को लागू करता है […]।
svick

1
@ स्क्विक अनुक्रम के तत्वों पर foreach(T x in sequence)स्पष्ट रूप से लागू होता है T। इसलिए यदि अनुक्रम एक सादा है IEnumerableऔर Tएक मूल्य प्रकार है तो यह आपके कोड में लिखे गए किसी भी स्पष्ट कलाकारों के बिना अनबॉक्स होगा। C # के बदसूरत हिस्सों में से एक।
कोडइन्चोस

@CodesInChaos "ऑटो-अनबॉक्सिंग" बहुत सामान्य लगता है, मुझे यह महसूस नहीं हुआ कि इस विशिष्ट विशेषता को संदर्भित किया गया है। (मुझे लगता है कि मेरे पास होना चाहिए, क्योंकि हम बात कर रहे थे foreach।)
svick
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.