2009-06-21 12 views

उत्तर

32

मार्कर इंटरफेस का उपयोग कक्षा की क्षमता को रन-टाइम पर एक विशिष्ट इंटरफ़ेस को लागू करने के रूप में चिह्नित करने के लिए किया जाता है।

Interface Design और .NET Type Design Guidelines - Interface Design सी # में विशेषताओं का उपयोग करने के पक्ष में मार्कर इंटरफेस के उपयोग को हतोत्साहित, लेकिन जैसा कि @Jay Bazuzi बताते हैं, यह आसान है विशेषताओं के लिए की तुलना में मार्कर इंटरफेस के लिए जाँच करने के लिए: तो बजाय o is I

इस:

public interface IFooAssignable {} 

public class FooAssignableAttribute : IFooAssignable 
{ 
    ... 
} 

नेट दिशा निर्देशों सिफारिश की है कि आप ऐसा करते हैं:

public class FooAssignableAttribute : Attribute 
{ 
    ... 
} 

[FooAssignable] 
public class Foo 
{  
    ... 
} 
+36

एनईटी डिजाइन दिशानिर्देशों का सामना नहीं करना, गुणों की तुलना में मार्कर इंटरफेस की जांच करना आसान है। 'ओ मैं हूं' –

+21

इसके अलावा, हम मार्कर इंटरफेस के साथ जेनरिक का पूरी तरह से उपयोग कर सकते हैं, लेकिन विशेषताओं के साथ नहीं। –

+15

जबकि मुझे विशेषताओं से प्यार है और वे एक घोषणात्मक दृष्टिकोण से कैसे देखते हैं, वे रनटाइम पर प्रथम श्रेणी के नागरिक नहीं हैं और इसके साथ काम करने के लिए अपेक्षाकृत निम्न स्तर की नलसाजी की आवश्यकता होती है। –

6

एक मार्कर इंटरफ़ेस केवल एक इंटरफ़ेस है जो खाली है। एक वर्ग इस इंटरफ़ेस को कुछ कारणों से मेटाडेटा के रूप में उपयोग करने के लिए लागू करेगा। सी # में आप आमतौर पर अन्य भाषाओं में मार्कर इंटरफ़ेस का उपयोग करने के कारणों के लिए कक्षा को चिह्नित करने के लिए विशेषताओं का उपयोग करेंगे।

61

यह "मिच गेहूं" द्वारा प्रतिक्रिया के आधार पर एक स्पर्शक का थोड़ा सा है।

आम तौर पर, किसी भी समय मैं लोगों ढांचे डिज़ाइन दिशा निर्देशों का हवाला देते हैं देखते हैं, मैं हमेशा कि उल्लेख करना चाहता हूँ:

आप ढांचे डिज़ाइन दिशानिर्देशों समय के सबसे अधिक उपेक्षा आम तौर पर करना चाहिए।

यह फ्रेमवर्क डिज़ाइन दिशानिर्देशों के साथ किसी भी मुद्दे के कारण नहीं है। मुझे लगता है कि .NET ढांचा एक शानदार वर्ग पुस्तकालय है। फ्रेमवर्क डिजाइन दिशानिर्देशों से बहुत सारी शानदारता बहती है।

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

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

  1. कुछ
  2. को लागू करने के लिए अतिरिक्त कोड दोहराव में हो सकता है की सबसे सरल तरीका नहीं हो सकता है
  3. अतिरिक्त मिल सकता है रनटाइम ओवरहेड

.नेट फ्रेमवर्क बड़ा, वास्तव में बड़ा है। यह इतना बड़ा है कि यह मानना ​​बिल्कुल अनुचित होगा कि किसी के पास इसके हर पहलू के बारे में विस्तृत ज्ञान है। वास्तव में, यह मानना ​​अधिक सुरक्षित है कि अधिकतर प्रोग्रामर अक्सर उस ढांचे के हिस्सों का सामना करते हैं जो उन्होंने पहले कभी नहीं उपयोग किया है।

उस मामले में, एक API डिजाइनर के प्राथमिक लक्ष्यों के लिए कर रहे हैं:

  1. चीजें ढांचे के बाकी के साथ सुसंगत रखें
  2. एपीआई सतह क्षेत्र में अनावश्यक जटिलता को हटा दें

फ्रेमवर्क डिज़ाइन दिशानिर्देश डेवलपर्स को उन लक्ष्यों को पूरा करने वाले कोड बनाने के लिए प्रेरित करते हैं।

इसका मतलब है कि विरासत की परतों से बचने जैसी चीजें करना, भले ही इसका मतलब है डुप्लिकेटिंग कोड, या साझा अपवादकों का उपयोग करने के बजाय सभी अपवाद फेंकने कोड को "प्रवेश बिंदु" पर धक्का देना (ताकि स्टैक निशान डीबगर में अधिक समझ में आ सकें), और कई अन्य समान चीजें हैं।

प्राथमिक कारण यह है कि उन दिशा निर्देशों मार्कर इंटरफेस के बजाय विशेषताओं का उपयोग करने का सुझाव क्योंकि मार्कर इंटरफेस को हटाने वर्ग पुस्तकालय की विरासत संरचना और अधिक सुलभ बना देता है। विरासत पदानुक्रम के 30 प्रकार और 6 परतों वाला एक वर्ग आरेख पदानुक्रम के 15 प्रकार और 2 परतों के साथ एक बहुत ही चुनौतीपूर्ण है।

यदि वास्तव में आपके एपीआई का उपयोग करने वाले लाखों डेवलपर हैं, या आपका कोड बेस वास्तव में बड़ा है (100K LOC से अधिक कहें) तो उन दिशानिर्देशों का पालन करने से बहुत मदद मिल सकती है।

यदि 5 मिलियन डेवलपर 60 मिनट सीखने के बजाय एपीआई सीखने में 15 मिनट खर्च करते हैं, तो परिणाम 428 व्यक्ति वर्ष की शुद्ध बचत है। यह बहुत समय है।

अधिकांश परियोजनाओं, हालांकि, डेवलपर्स के लाखों लोगों को शामिल नहीं है, या 100K + एल ओ सी। एक ठेठ प्रोजेक्ट में, 4 डेवलपर्स और लगभग 50 के लोकल के साथ, धारणाओं का सेट बहुत अलग है। टीम के डेवलपर्स को कोड कैसे काम करता है इसकी एक बेहतर समझ होगी। इसका मतलब यह है कि यह उच्च गुणवत्ता वाले कोड को जल्दी से तैयार करने के लिए अनुकूलित करने के लिए और बग की मात्रा को कम करने और परिवर्तन करने के लिए आवश्यक प्रयास को कम करने के लिए बहुत अधिक समझ में आता है।

खर्च 1 सप्ताह कोड है कि .नेट फ्रेमवर्क के साथ संगत है विकास, बनाम 8 घंटे कोड बदलने के लिए आसान है और कम कीड़े में परिणाम कर सकते हैं कि लेखन:

  1. देर परियोजनाओं
  2. लोअर बोनस
  3. वृद्धि बग मायने रखता है
  4. अधिक समय कार्यालय में बिताया है, और समुद्र तट पीने Margaritas पर कम समय।

4,999,999 अन्य डेवलपर्स के बिना लागत को अवशोषित करने के लिए यह आमतौर पर इसके लायक नहीं है।

उदाहरण के लिए, मार्कर इंटरफेस के लिए परीक्षण एक "है" अभिव्यक्ति पर आता है, और परिणामस्वरूप कम कोड में गुण होते हैं।

तो मेरी सलाह है:

  1. ढांचे के दिशा निर्देशों के धार्मिक अगर आप वर्ग पुस्तकालयों विकसित कर रहे हैं (या UI विजेट्स) व्यापक प्रसार की खपत के लिए का पालन करें।
  2. उनमें से कुछ को अपनाने पर विचार करें यदि आपके प्रोजेक्ट
  3. में 100K LOC से अधिक है तो अन्यथा उन्हें पूरी तरह से अनदेखा करें।
+8

मैं व्यक्तिगत रूप से, लाइब्रेरी के रूप में लिखने वाला कोई भी कोड देखता हूं, मुझे बाद में उपयोग करने की आवश्यकता होगी। मुझे वास्तव में खपत का ख्याल नहीं है या नहीं - दिशानिर्देशों का पालन निरंतरता बढ़ता है, और मुझे आश्चर्य होता है जब मुझे अपने कोड को देखने और इसे बाद में समझने की आवश्यकता होती है ... –

+13

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

+4

+1 - ओपी के सवाल का काफी जवाब नहीं दिया - एमआई का उद्देश्य - लेकिन फिर भी बहुत उपयोगी है। – bzarah

3

एक मार्कर इंटरफ़ेस एक वर्ग को इस तरह से टैग करने की अनुमति देता है जो सभी वंश वर्गों पर लागू होगा। एक "शुद्ध" मार्कर इंटरफ़ेस परिभाषित या कुछ भी वारिस नहीं करेगा; एक अधिक उपयोगी प्रकार का मार्कर इंटरफेस एक ऐसा हो सकता है जो "अन्य" इंटरफ़ेस "विरासत" प्राप्त करता है लेकिन कोई नया सदस्य परिभाषित नहीं करता है। उदाहरण के लिए, यदि कोई इंटरफ़ेस "IReadableFoo" है, तो कोई भी "IImmutableFoo" इंटरफ़ेस को परिभाषित कर सकता है, जो "फू" जैसा व्यवहार करेगा, लेकिन इसका उपयोग करने वाले किसी भी व्यक्ति से वादा होगा कि कुछ भी इसके मूल्य को नहीं बदलेगा। एक रूटीन जो IImmutableFoo स्वीकार करता है, इसका उपयोग करने में सक्षम होगा क्योंकि यह एक इरेडेबलफू होगा, लेकिन दिनचर्या केवल उन वर्गों को स्वीकार करेगी जिन्हें IImmutableFoo लागू करने के रूप में घोषित किया गया था।

मैं "शुद्ध" मार्कर इंटरफेस के लिए बहुत सारे उपयोगों के बारे में नहीं सोच सकता। केवल एक ही मैं सोच सकता हूं कि अगर इक्वालिटी कॉम्पैडर (टी) है। डीफॉल्ट ऑब्जेक्ट लौटाएगा। किसी भी प्रकार के लिए एक्वाल्स जो IDoNotUseEqualityComparer को लागू करता है, भले ही इस प्रकार ने IEqualityComparer भी लागू किया हो। यह किसी को लिस्कोव प्रतिस्थापन सिद्धांत का उल्लंघन किए बिना एक असीमित अपरिवर्तनीय प्रकार की अनुमति देगा: यदि प्रकार समानता-परीक्षण से संबंधित सभी विधियों को सील करता है, तो व्युत्पन्न प्रकार अतिरिक्त फ़ील्ड जोड़ सकता है और उन्हें उत्परिवर्तनीय बना सकता है, लेकिन ऐसे क्षेत्रों का उत्परिवर्तन ' किसी भी बेस-प्रकार विधियों का उपयोग करके दिखाई नहीं दे रहा है। यह एक असीमित अपरिवर्तनीय वर्ग होने के लिए भयानक नहीं हो सकता है और या तो इक्वालिटी कॉम्पैयरर के किसी भी उपयोग से बचने के लिए हो सकता है। डीफॉल्ट या ट्रस्ट व्युत्पन्न कक्षाएं IEqualityComparer को लागू नहीं करने के लिए, लेकिन एक व्युत्पन्न वर्ग जो IEqualityComparer को कार्यान्वित करता है, एक आधारभूत वर्ग के रूप में दिखाई दे सकता है, वर्ग वस्तु।

18

चूंकि हर दूसरे उत्तर में कहा गया है कि "उन्हें टालना चाहिए", यह एक स्पष्टीकरण के लिए उपयोगी होगा।

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

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

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

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

एक "मार्कर इंटरफेस" और एक सामान्य इंटरफ़ेस के बीच अंतर यह है कि तरीकों के साथ एक अंतरफलक बाहर की दुनिया को बताता है जबकि एक खाली इंटरफ़ेस का तात्पर्य यह बाहर की दुनिया कह रही है कि यह कैसे इस्तेमाल किया जाना चाहिए कि यह कैसे इस्तेमाल किया जा सकता है ।

+1

किसी भी इंटरफ़ेस का प्राथमिक उद्देश्य कक्षाओं के बीच अंतर करना है जो उस इंटरफ़ेस से जुड़े अनुबंध का पालन करने का वादा करता है, और जो नहीं करते हैं। जबकि एक इंटरफ़ेस भी अनुबंध को पूरा करने के लिए आवश्यक किसी भी सदस्यों के कॉलिंग हस्ताक्षर की आपूर्ति के लिए ज़िम्मेदार है, यह सदस्यों के बजाए अनुबंध है, जो यह निर्धारित करता है कि किसी विशेष वर्ग द्वारा एक विशेष इंटरफ़ेस लागू किया जाना चाहिए या नहीं। यदि 'IConstructableFromString 'के लिए अनुबंध निर्दिष्ट करता है कि एक वर्ग' टी' केवल' आईसीओस्ट्रक्टेबल फ्रॉमस्ट्रिंग 'लागू कर सकता है यदि उसके पास स्थिर सदस्य है ... – supercat

+0

... 'सार्वजनिक स्थैतिक टी प्रोड्यूस फ्रॉमस्ट्रिंग (स्ट्रिंग पैरा);', एक साथी वर्ग इंटरफ़ेस में एक विधि 'सार्वजनिक स्थैतिक टी उत्पाद FromString (स्ट्रिंग पैरा) प्रदान कर सकते हैं जहां टी: IConstructableFromString '; यदि क्लाइंट कोड में 'टी [] मेकमैनी थिंग्स () जैसे टी: आईसीओस्ट्रक्टेबल फ्रॉमस्ट्रिंग ' जैसी कोई विधि थी, तो कोई भी उन नए प्रकारों को परिभाषित कर सकता है जो क्लाइंट कोड के साथ काम करने के लिए क्लाइंट कोड को संशोधित किए बिना काम कर सकते हैं।यदि मेटाडेटा क्लाइंट कोड में था, तो मौजूदा क्लाइंट द्वारा उपयोग के लिए नए प्रकार बनाना संभव नहीं होगा। – supercat

6

मार्कर इंटरफेस कभी-कभी एक आवश्यक बुराई हो सकता है जब कोई भाषा भेदभाव संघ प्रकारों का समर्थन नहीं करती है।

मान लीजिए आप एक विधि है जो उम्मीद है एक तर्क है जिसका प्रकार वास्तव में ए, बी, या सी से एक कई कार्यात्मक-प्रथम भाषाओं में (जैसे F#), इस तरह के एक प्रकार सफाई से के रूप में परिभाषित किया जा सकता है किया जाना चाहिए परिभाषित करना चाहते हैं:

type Arg = 
    | AArg of A 
    | BArg of B 
    | CArg of C 

हालांकि, ओओ-प्रथम भाषाओं जैसे सी # में, यह संभव नहीं है। यहां कुछ ऐसा हासिल करने का एकमात्र तरीका इंटरफ़ेस IArg को परिभाषित करना और इसके साथ "चिह्न" ए, बी और सी को परिभाषित करना है।

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

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

+0

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

3

इन दोनों एक्सटेंशन तरीकों मुद्दों स्कॉट विशेषताओं से अधिक का दावा पक्ष मार्कर इंटरफेस के सबसे समाधान होगा:

public static bool HasAttribute<T>(this ICustomAttributeProvider self) 
    where T : Attribute 
{ 
    return self.GetCustomAttributes(true).Any(o => o is T); 
} 

public static bool HasAttribute<T>(this object self) 
    where T : Attribute 
{ 
    return self != null && self.GetType().HasAttribute<T>() 
} 

अब आपके पास:

if (o.HasAttribute<FooAssignableAttribute>()) 
{ 
    //... 
} 

बनाम:

if (o is IFooAssignable) 
{ 
    //... 
} 

मैं यह देखने में असफल रहा कि एपीआई बनाने से पहले पैटर्न की तुलना में 5 गुना अधिक समय लगेगा दूसरा, स्कॉट का दावा है।

0

मार्कर खाली इंटरफेस हैं। एक मार्कर या तो वहां है या यह नहीं है।

वर्ग फू: IConfidential

यहाँ हम गोपनीय होने के रूप में फू निशान। कोई वास्तविक अतिरिक्त गुण या गुण आवश्यक नहीं है।

0

मार्कर इंटरफ़ेस एक कुल रिक्त इंटरफ़ेस है जिसमें कोई शरीर/डेटा-सदस्य/कार्यान्वयन नहीं है।
एक कक्षा आवश्यक होने पर मार्कर इंटरफ़ेस लागू करता है, यह केवल "चिह्न" है; इसका मतलब है कि यह जेवीएम को बताता है कि विशेष वर्ग क्लोनिंग के उद्देश्य के लिए है, इसलिए इसे क्लोन करने दें। यह विशेष वर्ग अपनी वस्तुओं को क्रमबद्ध करना है, इसलिए कृपया इसकी वस्तुओं को क्रमबद्ध करने की अनुमति दें।

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