लिस्ट <T> से विरासत में क्यों नहीं?


1398

अपने कार्यक्रमों की योजना बनाते समय, मैं अक्सर इस तरह की सोच की एक श्रृंखला के साथ शुरुआत करता हूं:

एक फुटबॉल टीम सिर्फ फुटबॉल खिलाड़ियों की एक सूची है। इसलिए, मुझे इसका प्रतिनिधित्व करना चाहिए:

var football_team = new List<FootballPlayer>();

इस सूची का क्रम उस क्रम का प्रतिनिधित्व करता है जिसमें खिलाड़ी रोस्टर में सूचीबद्ध होते हैं।

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

तो मुझे लगता है:

ठीक है, एक फुटबॉल टीम खिलाड़ियों की एक सूची की तरह है, लेकिन इसके अलावा, इसमें एक नाम (ए string) और एक रनिंग कुल स्कोर (ए int) है। .NET फ़ुटबॉल टीमों के भंडारण के लिए एक वर्ग प्रदान नहीं करता है, इसलिए मैं अपनी कक्षा बनाऊंगा। सबसे समान और प्रासंगिक मौजूदा संरचना है List<FootballPlayer>, इसलिए मुझे इससे विरासत मिलेगी:

class FootballTeam : List<FootballPlayer> 
{ 
    public string TeamName; 
    public int RunningTotal 
}

लेकिन यह पता चलता है कि एक गाइडलाइन कहती है कि आपको विरासत में नहीं लेना चाहिएList<T> । मैं इस गाइडलाइन से दो तरह से भ्रमित हूं।

क्यों नहीं?

जाहिरा तौर Listपर किसी भी तरह प्रदर्शन के लिए अनुकूलित है । ऐसा कैसे? यदि मैं विस्तार करता हूं तो मुझे कौन सी प्रदर्शन समस्याएं होंगी List? क्या वास्तव में टूट जाएगा?

एक अन्य कारण जो मैंने देखा है वह Listयह है कि Microsoft द्वारा प्रदान किया गया है, और मुझे इस पर कोई नियंत्रण नहीं है, इसलिए मैं "सार्वजनिक एपीआई" को उजागर करने के बाद इसे बाद में नहीं बदल सकता । लेकिन मैं इसे समझने के लिए संघर्ष करता हूं। सार्वजनिक एपीआई क्या है और मुझे इसकी देखभाल क्यों करनी चाहिए? यदि मेरी वर्तमान परियोजना में यह सार्वजनिक एपीआई नहीं है, तो क्या मैं इस दिशानिर्देश को सुरक्षित रूप से अनदेखा कर सकता हूं? अगर मुझे विरासत में मिली List और यह पता चला कि मुझे सार्वजनिक एपीआई की आवश्यकता है, तो मुझे क्या कठिनाइयाँ होंगी?

इससे भी फर्क क्यों पड़ता है? एक सूची एक सूची है। क्या संभवतः बदल सकता है? मैं संभवतः क्या बदलना चाहता हूं?

और अंत में, अगर Microsoft नहीं चाहता था कि मुझे विरासत से मिले List, तो उन्होंने कक्षा क्यों नहीं बनाई sealed?

मुझे और क्या उपयोग करना चाहिए?

जाहिरा तौर पर, कस्टम संग्रह के लिए, Microsoft ने एक Collectionवर्ग प्रदान किया है जिसे इसके बजाय बढ़ाया जाना चाहिए List। लेकिन इस वर्ग के बहुत नंगे है, और कई उपयोगी चीजें, नहीं है जैसेAddRange उदाहरण के लिए,। jvitor83 का जवाब उस विशेष पद्धति के लिए एक प्रदर्शन तर्क प्रदान करता है, लेकिन कैसे एक धीमी गति AddRangeसे बेहतर नहीं है AddRange?

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

मैंने सुझाव दिए हैं जैसे कि लागू करना IList। बस नहीं। यह बॉयलरप्लेट कोड की दर्जनों लाइनें हैं जो मुझे कुछ भी नहीं देती हैं।

अंत में, कुछ कुछ में लपेटने का सुझाव देते Listहैं:

class FootballTeam 
{ 
    public List<FootballPlayer> Players; 
}

इसके साथ दो मुश्किलें हैं:

  1. यह मेरा कोड अनावश्यक रूप से क्रिया करता है। मुझे अब my_team.Players.Countबस के बजाय कॉल करना होगा my_team.Count। शुक्र है, C # के साथ मैं अनुक्रमित को पारदर्शी बनाने के लिए इंडेक्सर्स को परिभाषित कर सकता हूं, और आंतरिक के सभी तरीकों को आगे बढ़ा सकता हूं List... लेकिन यह बहुत कोड है! मुझे उस काम के लिए क्या मिलेगा?

  2. यह सिर्फ सादा मतलब नहीं है। एक फुटबॉल टीम के पास खिलाड़ियों की सूची नहीं है। यह है खिलाड़ियों की सूची। आप यह नहीं कहते "जॉन मैकफुटबॉलर SomeTeam के खिलाड़ियों में शामिल हो गया है"। आप कहते हैं "जॉन SomeTeam में शामिल हो गए हैं"। आप "स्ट्रिंग के पात्रों" के लिए एक पत्र नहीं जोड़ते हैं, आप एक स्ट्रिंग में एक पत्र जोड़ते हैं। आप किसी पुस्तकालय की पुस्तकों में पुस्तक नहीं जोड़ते हैं, आप पुस्तकालय में पुस्तक जोड़ते हैं।

मुझे पता है कि "हुड के नीचे" क्या होता है, इसे "एक्स की वाई की आंतरिक सूची में जोड़ना" कहा जा सकता है, लेकिन यह दुनिया के बारे में सोचने का एक बहुत ही सहज ज्ञान युक्त तरीका है।

मेरा प्रश्न (संक्षेप में)

एक डेटा संरचना है, जो, "तार्किक" ( "मनुष्य के मन के लिए" कहने के लिए है कि,) सिर्फ एक है का प्रतिनिधित्व करने का सही तरीका क्या है सी # listके thingsकुछ घंटियां और सीटियां के साथ?

क्या List<T>हमेशा से अस्वीकार्य है? यह कब स्वीकार्य है? क्यों नहीं? एक प्रोग्रामर को क्या विचार करना चाहिए, यह तय करते समय कि क्या विरासत में मिला है List<T>या नहीं?


90
इसलिए, क्या आपका प्रश्न वास्तव में वंशानुक्रम का उपयोग करने के लिए है (एक वर्ग है-एक आयत क्योंकि यह हमेशा एक वर्ग प्रदान करने के लिए उचित है जब एक जेनेरिक आयत का अनुरोध किया गया था) और रचना का उपयोग करने के लिए (एक फुटबॉलटैब में फुटबॉल खिलाड़ियों की एक सूची है, इसके अलावा) अन्य संपत्तियों के लिए जो इसे "मौलिक" के रूप में, एक नाम की तरह) हैं? क्या अन्य प्रोग्रामर भ्रमित हो सकते हैं यदि कोड में कहीं और आप उन्हें एक फुटबॉलटेम पास करते हैं जब वे एक साधारण सूची की उम्मीद कर रहे थे?
फ्लाइट ओडिसी

77
क्या होगा अगर मैं आपको बताऊं कि एक फुटबॉल टीम एक व्यवसायिक कंपनी है जो OWNS के खिलाडियों की सूची के बजाय अतिरिक्त अतिरिक्त गुणों वाले खिलाड़ियों की नंगे सूची में है?
STT LCU

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

45
@FlightOdyssey: मान लीजिए कि आपके पास एक तरीका है स्क्वैश रेक्टेंगल जो आयत लेता है, इसकी ऊंचाई को आधा करता है, और इसकी चौड़ाई को दोगुना करता है। अब एक आयत में पास करें जो 4x4 का होता है लेकिन प्रकार के आयत का होता है, और एक वर्ग जो 4x4 होता है। स्क्वैश रेक्टेंगल के बाद वस्तु के आयाम क्या कहलाते हैं? आयत के लिए स्पष्ट रूप से यह 2x8 है। यदि वर्ग 2x8 है तो वह वर्ग नहीं रह जाता है; यदि यह 2x8 नहीं है, तो समान आकृति पर एक ही ऑपरेशन एक अलग परिणाम उत्पन्न करता है। निष्कर्ष है कि एक परिवर्तनशील वर्ग है नहीं आयत का एक प्रकार।
एरिक लिपर्ट

29
@ गैंग्नस: आपका बयान केवल झूठा है; एक वास्तविक उपवर्ग में कार्यक्षमता होना आवश्यक है जो सुपरक्लास का सुपरसेट है। एक stringसब कुछ एक ऐसा करना पड़ता है objectक्या कर सकते हैं और अधिक
एरिक लिपर्ट

जवाबों:


1564

यहाँ कुछ अच्छे जवाब हैं। मैं उन्हें निम्नलिखित बिंदुओं से जोड़ूंगा।

डेटा संरचना का प्रतिनिधित्व करने का सही C # तरीका क्या है, जो "तार्किक रूप से" (जो कि, "मानव मन के लिए" है) बस कुछ घंटियों और सीटी के साथ चीजों की एक सूची है?

किसी भी दस गैर-कंप्यूटर-प्रोग्रामर लोगों से पूछें, जो रिक्त स्थान को भरने के लिए फुटबॉल के अस्तित्व से परिचित हैं:

एक फुटबॉल टीम एक विशेष प्रकार का _____ है

क्या किसी ने "फुटबॉल खिलाड़ियों की सूची कुछ घंटियों और सीटी के साथ", या क्या वे सभी "स्पोर्ट्स टीम" या "क्लब" या "संगठन" कहे थे? आपकी धारणा यह है कि एक फुटबॉल टीम एक विशेष प्रकार की खिलाड़ियों की सूची है जो आपके मानव मन और आपके मानव मन में है।

List<T>एक तंत्र है । फुटबॉल टीम एक व्यावसायिक वस्तु है - अर्थात, एक ऐसी वस्तु जो कुछ अवधारणा का प्रतिनिधित्व करती है जो कार्यक्रम के व्यावसायिक क्षेत्र में है। उन मिश्रण मत करो! एक फुटबॉल टीम एक तरह की टीम है; यह एक है रोस्टर एक रोस्टर, खिलाड़ियों की एक सूची है । एक रोस्टर खिलाड़ियों की एक विशेष प्रकार की सूची नहीं है । एक रोस्टर है खिलाड़ियों की एक सूची। तो एक संपत्ति है Rosterकि कहा जाता है एक बनाते हैं List<Player>। और ReadOnlyList<Player>जब तक आप इस पर रहें , तब तक जब तक आप यह नहीं मानते कि फुटबॉल टीम के बारे में जानने वाले को रोस्टर से खिलाड़ियों को हटाना पड़ता है ।

क्या List<T>हमेशा से अस्वीकार्य है?

अस्वीकार्य कौन है? मेरे? नहीं।

यह कब स्वीकार्य है?

जब आप एक तंत्र का निर्माण कर रहे हैं जो तंत्र का विस्तार करता List<T>है

एक प्रोग्रामर को क्या विचार करना चाहिए, यह तय करते समय कि क्या विरासत में मिला है List<T>या नहीं?

क्या मैं एक तंत्र या एक व्यावसायिक वस्तु का निर्माण कर रहा हूं ?

लेकिन यह बहुत कोड है! मुझे उस सभी काम के लिए क्या मिलेगा?

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

अपडेट करें

मैंने इसे कुछ और सोचा और खिलाड़ियों की सूची के रूप में एक फुटबॉल टीम को मॉडल नहीं करने का एक और कारण है। वास्तव में यह एक बुरा विचार के रूप में एक फुटबॉल टीम मॉडल करने के लिए हो सकता है होने भी खिलाड़ियों की एक सूची। खिलाड़ियों की एक सूची के रूप में टीम के साथ समस्या यह है कि आपको जो मिला है वह समय में एक टीम का स्नैपशॉट है । मुझे नहीं पता कि आपका व्यावसायिक मामला इस वर्ग के लिए क्या है, लेकिन अगर मेरे पास एक वर्ग है जो एक फुटबॉल टीम का प्रतिनिधित्व करता है, तो मैं यह सवाल पूछना चाहता हूं कि "2003 और 2013 के बीच चोट के कारण कितने Seahawks खिलाड़ी खेल से चूक गए?" या "क्या डेनवर खिलाड़ी जो पहले किसी अन्य टीम के लिए खेले थे, यार्ड में सबसे अधिक साल-दर-साल वृद्धि हुई थी?" या " क्या इस साल पिगर्स सभी तरह से चले गए? "

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


84
हालाँकि अन्य उत्तर बहुत मददगार रहे हैं, मुझे लगता है कि यह मेरी चिंताओं को सबसे सीधे संबोधित करता है। कोड की मात्रा को बढ़ाने के लिए, आप सही हैं कि यह अंत में उतना काम नहीं है, लेकिन मैं बहुत आसानी से भ्रमित हो जाता हूं जब मैं अपने कार्यक्रम में कुछ कोड को यह समझे बिना शामिल करता हूं कि मैं इसे क्यों शामिल कर रहा हूं।
शानदार

127
@ सुपरब्रैड: खुशी है कि मैं मदद कर सकता हूं! आप उन संदेहों को सुनने के लिए सही हैं; अगर आपको समझ में नहीं आ रहा है कि आप कुछ कोड क्यों लिख रहे हैं, या तो इसका पता लगाएँ, या अलग-अलग कोड लिखें जो आप समझते हैं।
एरिक लिपिपर्ट

48
@ मेहरदाद लेकिन आप अनुकूलन के सुनहरे नियमों को भूल जाते हैं: 1) ऐसा मत करो, 2) अभी मत करो, और 3) प्रदर्शन प्रोफाइल के बिना यह करने के लिए पहले मत करो कि अनुकूलन की आवश्यकता क्या है।
AJMansfield

107
@ मेहरदाद: ईमानदारी से, यदि आपके आवेदन के लिए आवश्यक है कि आप प्रदर्शन के बोझ, कहने के तरीके, आभासी तरीकों की परवाह करते हैं, तो कोई भी आधुनिक भाषा (C #, Java, आदि) आपके लिए भाषा नहीं है। मेरे पास यहीं एक लैपटॉप है जो एक बच्चे के रूप में एक साथ खेले जाने वाले हर आर्केड गेम का अनुकरण कर सकता है । यह मुझे यहां और वहां अप्रत्यक्ष स्तर के बारे में चिंता करने की अनुमति नहीं देता है।
एरिक लिपर्ट

44
@ सुपरप्रबेक: अब हम निश्चित रूप से स्पेक्ट्रम की "रचना नहीं विरासत" अंत में हैं। एक रॉकेट रॉकेट भागों से बना है । एक रॉकेट "एक विशेष प्रकार की भागों की सूची" नहीं है! मैं आपको सुझाव दूंगा कि आप इसे और नीचे ट्रिम करें; क्यों एक सूची, एक के विपरीत IEnumerable<T>- एक अनुक्रम ?
एरिक लिपर्ट

161

वाह, आपकी पोस्ट में प्रश्नों और बिंदुओं की पूरी श्रृंखला है। Microsoft से प्राप्त अधिकांश तर्क बिल्कुल बिंदु पर हैं। सब कुछ के साथ शुरू करते हैंList<T>

  • List<T> है अत्यधिक अनुकूलित। इसका मुख्य उपयोग किसी वस्तु के निजी सदस्य के रूप में उपयोग किया जाना है।
  • Microsoft ने इसे सील नहीं किया, क्योंकि कभी-कभी आप एक ऐसा वर्ग बनाना चाहते हैं जिसका मित्र नाम हो class MyList<T, TX> : List<CustomObject<T, Something<TX>> { ... }:। अब यह करना जितना आसान है var list = new MyList<int, string>();
  • CA1002: जेनेरिक सूचियों को उजागर न करें : मूल रूप से, भले ही आप इस ऐप को एकमात्र डेवलपर के रूप में उपयोग करने की योजना बनाते हों, यह अच्छी कोडिंग प्रथाओं के साथ विकसित करने के लिए सार्थक है, इसलिए वे आपके और दूसरे स्वभाव में शामिल हो जाते हैं। आपको अभी भी सूची को उजागर करने की अनुमति है जैसे IList<T>कि आपको किसी भी उपभोक्ता को अनुक्रमित सूची की आवश्यकता होती है। चलिए आप बाद में एक वर्ग के भीतर कार्यान्वयन को बदलते हैं।
  • Microsoft ने Collection<T>बहुत सामान्य बनाया क्योंकि यह एक सामान्य अवधारणा है ... नाम यह सब कहता है; यह सिर्फ एक संग्रह है। इस तरह के रूप में अधिक सटीक संस्करण हैं SortedCollection<T>, ObservableCollection<T>, ReadOnlyCollection<T>जिनमें से प्रत्येक को लागू, आदिIList<T> लेकिन नहीं List<T>
  • Collection<T>सदस्यों के लिए अनुमति देता है (जैसे कि जोड़ें, निकालें, आदि) क्योंकि वे आभासी हैं, ओवरराइड करने के लिए। List<T>नहीं करता।
  • आपके प्रश्न का अंतिम भाग हाजिर है। एक फुटबॉल टीम सिर्फ खिलाड़ियों की सूची से अधिक है, इसलिए यह एक ऐसा वर्ग होना चाहिए जिसमें खिलाड़ियों की सूची हो। सोचो बनाम विरासत संरचना । एक फुटबॉल टीम में खिलाड़ियों की सूची होती है (रोस्टर), यह खिलाड़ियों की सूची नहीं है।

अगर मैं यह कोड लिख रहा होता तो क्लास शायद कुछ इस तरह दिखाई देती:

public class FootballTeam
{
    // Football team rosters are generally 53 total players.
    private readonly List<T> _roster = new List<T>(53);

    public IList<T> Roster
    {
        get { return _roster; }
    }

    // Yes. I used LINQ here. This is so I don't have to worry about
    // _roster.Length vs _roster.Count vs anything else.
    public int PlayerCount
    {
        get { return _roster.Count(); }
    }

    // Any additional members you want to expose/wrap.
}

6
" आपकी पोस्ट में प्रश्नों की पूरी संख्या है " - ठीक है, मैंने कहा कि मैं पूरी तरह से भ्रमित था। @ Readonly के प्रश्न से लिंक करने के लिए धन्यवाद, अब मैं देखता हूं कि मेरे प्रश्न का एक बड़ा हिस्सा अधिक सामान्य संरचना बनाम वंशानुक्रम की समस्या का एक विशेष मामला है।
शानदार

3
@ ब्रायन: सिवाय इसके कि आप उपनाम का उपयोग करके एक जेनेरिक नहीं बना सकते, सभी प्रकार के ठोस होने चाहिए। मेरे उदाहरण में, List<T>एक निजी आंतरिक वर्ग के रूप में विस्तारित किया गया है जो उपयोग और घोषणा को सरल बनाने के लिए जेनरिक का उपयोग करता है List<T>। अगर विस्तार महज था class FootballRoster : List<FootballPlayer> { }, तो हाँ मैं इसके बजाय एक उपनाम का उपयोग कर सकता था। मुझे लगता है कि यह ध्यान देने योग्य है कि आप अतिरिक्त सदस्य / कार्यक्षमता जोड़ सकते हैं, लेकिन यह सीमित है क्योंकि आप महत्वपूर्ण सदस्यों को ओवरराइड नहीं कर सकते List<T>
मेरा

6
यदि यह प्रोग्रामर थे। तो, मैं उत्तर मतों की वर्तमान सीमा से सहमत होता हूं, लेकिन, जैसा कि यह एक SO पोस्ट है, यह उत्तर कम से कम C # (.NET) विशिष्ट मुद्दों का जवाब देने का प्रयास करता है, हालांकि निश्चित सामान्य हैं डिजाइन मुद्दों।
मार्क हर्ड

7
Collection<T> allows for members (i.e. Add, Remove, etc.) to be overriddenअब है कि एक अच्छा कारण सूची से प्राप्त करना नहीं है। दूसरों के जवाब में बहुत अधिक दर्शन हैं।
नवीन

10
@ मैं: मुझे संदेह है कि आपका मतलब "सवालों का जवाब" है, क्योंकि एक खोजी कुत्ता एक जासूस है।
बल्लेबाजी

152
class FootballTeam : List<FootballPlayer> 
{ 
    public string TeamName; 
    public int RunningTotal;
}

पिछला कोड का अर्थ है: फुटबॉल खेलने वाले गली के लोगों का एक झुंड, और उनका एक नाम है। कुछ इस तरह:

फुटबॉल खेलने वाले लोग

वैसे भी, यह कोड (मेरे जवाब से)

public class FootballTeam
{
    // A team's name
    public string TeamName; 

    // Football team rosters are generally 53 total players.
    private readonly List<T> _roster = new List<T>(53);

    public IList<T> Roster
    {
        get { return _roster; }
    }

    public int PlayerCount
    {
        get { return _roster.Count(); }
    }

    // Any additional members you want to expose/wrap.
}

इसका मतलब है: यह एक फुटबॉल टीम है जिसमें प्रबंधन, खिलाड़ी, प्रवेश, आदि कुछ इस तरह हैं:

मैनचेस्टर यूनाइटेड टीम के सदस्यों (और अन्य विशेषताओं) को दिखाने वाली छवि

यह आपके तर्क को चित्रों में प्रस्तुत किया गया है ...


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

3
अधिक अनुकूलितprivate readonly List<T> _roster = new List<T>(44);
SiD

2
System.Linqनाम स्थान का आयात करना आवश्यक है ।
डेविड कैन्निज़ो

1
दृश्यों के लिए: +1
V.7

115

यह रचना बनाम विरासत का एक उत्कृष्ट उदाहरण है

इस विशिष्ट मामले में:

क्या टीम अतिरिक्त व्यवहार वाले खिलाड़ियों की सूची है

या

क्या टीम अपने आप में एक वस्तु है जो खिलाड़ियों की सूची में शामिल है।

सूची का विस्तार करके आप कई तरीकों से खुद को सीमित कर रहे हैं:

  1. आप पहुँच को प्रतिबंधित नहीं कर सकते हैं (उदाहरण के लिए, रोस्टर बदलने वाले लोगों को रोकना)। आपको सभी लिस्ट मेथड मिल जाते हैं, चाहे आपको उन सभी की आवश्यकता हो या नहीं।

  2. यदि आप अन्य चीजों की सूची भी चाहते हैं तो क्या होगा। उदाहरण के लिए, टीमों के पास कोच, प्रबंधक, पंखे, उपकरण आदि हैं, उनमें से कुछ अच्छी तरह से अपने आप में सूचियां हो सकती हैं।

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

रचना - जिस वस्तु को आप अपनी वस्तु के अंदर चाहते हैं उसे देने वाली वस्तु सहित।

वंशानुक्रम - आपकी वस्तु उस वस्तु का एक उदाहरण बन जाती है जिसमें वह व्यवहार होता है जो आप चाहते हैं।

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


1
# 2 पर विस्तार करना, किसी सूची के पास सूची के लिए कोई अर्थ नहीं रखता है ।
क्रन्चर

पहला, प्रश्न का रचना बनाम विरासत से कोई लेना-देना नहीं है। जवाब है ओपी अधिक विशिष्ट प्रकार की सूची को लागू नहीं करना चाहता है, इसलिए उसे सूची <> का विस्तार नहीं करना चाहिए। मेरा कारण है कि स्टैकओवरफ्लो पर आपके बहुत अधिक अंक हैं और आपको यह स्पष्ट रूप से पता होना चाहिए और लोगों को आपके द्वारा कहे गए विश्वास पर भरोसा करना चाहिए, इसलिए अब तक 55 लोगों का एक मंत्री, जो अपवित्र हैं और जिनके विचार भ्रमित हैं या तो एक तरीका मानते हैं या दूसरा बनाने के लिए ठीक है एक प्रणाली लेकिन स्पष्ट रूप से यह नहीं है! # नो-रेज
मौरो सेम्पीटरो

6
@sam वह सूची का व्यवहार चाहता है। उसके पास दो विकल्प हैं, वह सूची (वंशानुक्रम) का विस्तार कर सकता है या वह अपनी वस्तु (रचना) के अंदर एक सूची शामिल कर सकता है। शायद आपने 55 लोगों के गलत होने के बजाय सवाल या जवाब का गलत हिस्सा लिया हो और आप सही हैं? :)
टिम बी

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

3
ओपी ने रचना के लिए नहीं पूछा, लेकिन उपयोग का मामला X का स्पष्ट उदाहरण है: Y समस्या जिसमें से 4 ऑब्जेक्ट उन्मुख प्रोग्रामिंग सिद्धांतों में से एक टूट गया है, दुरुपयोग किया गया है, या पूरी तरह से समझा नहीं गया है। अधिक स्पष्ट उत्तर या तो स्टैक या क्यू (जो उपयोग के मामले को फिट करने के लिए प्रकट नहीं होता है) या रचना को समझने के लिए एक विशेष संग्रह लिखता है। एक फुटबॉल टीम फुटबॉल खिलाड़ियों की सूची नहीं है। ओपी ने स्पष्ट रूप से पूछा है कि क्या यह अप्रासंगिक है, एब्सट्रैक्शन, एनकैप्सुलेशन, इनहेरिटेंस, और पॉलीमॉर्फिज्म को समझने के बिना, वे जवाब नहीं समझेंगे, एर्गो, एक्स: वाई एमोक
जूलिया मैक्चुइगन

67

जैसा कि सभी ने बताया है, खिलाड़ियों की एक टीम खिलाड़ियों की सूची नहीं है। यह गलती कई लोगों द्वारा हर जगह की जाती है, शायद विशेषज्ञता के विभिन्न स्तरों पर। अक्सर समस्या सूक्ष्म और कभी-कभी बहुत ही स्थूल होती है, जैसा कि इस मामले में है। इस तरह के डिजाइन खराब हैं क्योंकि ये लिस्कोव सबस्टीट्यूशन सिद्धांत का उल्लंघन करते हैं । इंटरनेट में इस अवधारणा को समझाने वाले कई अच्छे लेख हैं जैसे, http://en.wikipedia.org/wiki/Liskov_substitution_principle

सारांश में, माता-पिता / बच्चों के बीच कक्षाओं में दो नियमों को संरक्षित किया जाना है:

  • एक बच्चे को माता-पिता को पूरी तरह से परिभाषित करने से कम किसी विशेषता की आवश्यकता नहीं होनी चाहिए।
  • एक माता-पिता को बच्चे को पूरी तरह से परिभाषित करने के अलावा किसी विशेषता की आवश्यकता नहीं होनी चाहिए।

दूसरे शब्दों में, एक अभिभावक बच्चे की एक आवश्यक परिभाषा है, और एक बच्चा एक अभिभावक की पर्याप्त परिभाषा है।

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

  • क्या एक फुटबॉल टीम फुटबॉल खिलाड़ियों की सूची है? (एक सूची के सभी गुण एक ही अर्थ में एक टीम पर लागू होते हैं)
    • क्या एक टीम समरूप संस्थाओं का संग्रह है? हां, टीम प्लेयर्स का एक संग्रह है
    • क्या खिलाड़ियों को टीम की स्थिति के बारे में बताने का आदेश शामिल है और क्या टीम यह सुनिश्चित करती है कि अनुक्रम को तब तक संरक्षित रखा जाए जब तक कि स्पष्ट रूप से बदल न जाए? नहीं, और नहीं
    • क्या खिलाड़ियों को टीम में उनकी क्रमिक स्थिति के आधार पर शामिल / शामिल किए जाने की उम्मीद है? नहीं

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

इस बिंदु पर मैं यह कहना चाहूंगा कि एक टीम वर्ग को मेरी राय में, एक सूची का उपयोग करके भी लागू नहीं किया जाना चाहिए; यह ज्यादातर मामलों में सेट डेटा संरचना (उदाहरण के लिए हैशसेट) का उपयोग करके लागू किया जाना चाहिए।


8
सूची बनाम सेट पर अच्छी पकड़। यह केवल सामान्य रूप से की गई एक त्रुटि प्रतीत होती है। जब संग्रह में किसी तत्व का केवल एक उदाहरण हो सकता है, तो किसी प्रकार का सेट, या शब्दकोश कार्यान्वयन के लिए एक पसंदीदा उम्मीदवार होना चाहिए। एक ही नाम के दो खिलाड़ियों वाली टीम होना ठीक है। एक ही खिलाड़ी को एक ही समय में दो बार शामिल करना ठीक नहीं है।
फ्रेड मिशेल

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

1
@TonyD खैर, मैं जिन बिंदुओं को उठा रहा हूं, वह यह नहीं है कि किसी को "यदि डेटा संरचना उपयोगी है से अधिक करता है" तो जांच करनी चाहिए। यह जांचना है कि "यदि माता-पिता डेटा संरचना ऐसा कुछ करते हैं, जो कि बच्चे के वर्ग के व्यवहार के लिए अप्रासंगिक, अर्थहीन या प्रति-सहज है।"
सत्येन रैना

1
@TonyD वास्तव में एक अभिभावक से प्राप्त अप्रासंगिक विशेषताओं के साथ एक समस्या है क्योंकि यह कई मामलों में नकारात्मक परीक्षणों को विफल कर देगा। एक प्रोग्रामर मानव {खाने) का विस्तार कर सकता है; Daud(); लिखना (); गोरिल्ला {खाओ () से; Daud(); स्विंग ();} यह सोचकर कि स्विंग करने में सक्षम होने की एक अतिरिक्त विशेषता के साथ मानव के साथ कुछ भी गलत नहीं है। और फिर एक खेल की दुनिया में अपने मानव अचानक पेड़ों पर झूलते हुए सभी माना भूमि बाधाओं को बायपास करने के लिए शुरू होता है। जब तक स्पष्ट रूप से निर्दिष्ट नहीं किया जाता है, एक व्यावहारिक मानव को स्विंग करने में सक्षम नहीं होना चाहिए। इस तरह के एक डिजाइन ने अप्पी को गाली देने और भ्रमित करने के लिए बहुत खुला छोड़ दिया
सत्यन रैना

1
@TonyD मैं यह सुझाव नहीं दे रहा हूं कि प्लेयर वर्ग को हैशसेट से लिया जाए। मैं सुझाव दे रहा हूं कि प्लेयर क्लास को 'ज्यादातर मामलों में' को कंपोज़िशन के जरिए HashSet का उपयोग करके लागू किया जाना चाहिए और यह पूरी तरह से एक कार्यान्वयन स्तर का विवरण है, न कि डिज़ाइन स्तर का एक (यही कारण है कि मैंने इसे अपने उत्तर के लिए एक सिडेनोट के रूप में उल्लेख किया है)। यह बहुत अच्छी तरह से एक सूची का उपयोग करके लागू किया जा सकता है अगर इस तरह के कार्यान्वयन के लिए एक वैध औचित्य है। तो अपने प्रश्न का उत्तर देने के लिए, क्या O (1) कुंजी द्वारा देखना आवश्यक है? नहीं, इसलिए किसी खिलाड़ी को हैशसेट से भी नहीं बढ़ाया जाना चाहिए।
सत्यन रैना

50

क्या होगा अगर FootballTeamमुख्य टीम के साथ एक रिजर्व टीम है?

class FootballTeam
{
    List<FootballPlayer> Players { get; set; }
    List<FootballPlayer> ReservePlayers { get; set; }
}

आप उसके साथ कैसे मॉडल बनाएंगे?

class FootballTeam : List<FootballPlayer> 
{ 
    public string TeamName; 
    public int RunningTotal 
}

संबंध स्पष्ट रूप से एक है और एक नहीं है

या RetiredPlayers?

class FootballTeam
{
    List<FootballPlayer> Players { get; set; }
    List<FootballPlayer> ReservePlayers { get; set; }
    List<FootballPlayer> RetiredPlayers { get; set; }
}

अंगूठे के एक नियम के रूप में, यदि आप कभी भी एक संग्रह से विरासत चाहते हैं, तो कक्षा का नाम दें SomethingCollection

क्या आपका SomethingCollectionशब्दार्थ समझ में आता है? यदि आपका प्रकार एक संग्रह है तो ही ऐसा करें Something

के मामले में FootballTeamयह सही नहीं लगता है। A Teamसे अधिक है Collection। A के Teamपास कोच, ट्रेनर आदि हो सकते हैं क्योंकि अन्य उत्तर बताए गए हैं।

FootballCollectionफुटबॉल के एक संग्रह की तरह लगता है या शायद फुटबॉल का एक संग्रह। TeamCollection, टीमों का एक संग्रह।

FootballPlayerCollectionलगता है कि खिलाड़ियों का एक संग्रह जो एक वर्ग के लिए एक वैध नाम होगा जो विरासत में मिला है List<FootballPlayer>अगर आप वास्तव में ऐसा करना चाहते हैं।

List<FootballPlayer>से निपटने के लिए वास्तव में एक अच्छा प्रकार है। शायदIList<FootballPlayer> अगर आप इसे एक विधि से वापस कर रहे हैं।

संक्षेप में

अपने आप से पूछो

  1. है X एक Y? या है X एक Y?

  2. क्या मेरे वर्ग के नाम का मतलब है कि वे क्या हैं?


हर खिलाड़ी के प्रकार या तो से संबंधित के रूप में यह वर्गीकृत चाहते हैं DefensivePlayers, OffensivePlayersया OtherPlayers, यह वैध तरीके से उपयोगी हो सकता है एक प्रकार है जो कोड है जो उम्मीद एक से इस्तेमाल किया जा सकता है करने के लिए List<Player>, लेकिन यह भी शामिल सदस्यों DefensivePlayers, OffsensivePlayersया SpecialPlayersप्रकार के IList<DefensivePlayer>, IList<OffensivePlayer>, और IList<Player>। अलग-अलग सूचियों को कैश करने के लिए एक अलग ऑब्जेक्ट का उपयोग किया जा सकता है, लेकिन एक ही ऑब्जेक्ट के भीतर उन्हें
एनकैप्सुलेट

... इस तथ्य के लिए एक क्यू के रूप में कि मुख्य सूची बदल गई है और उप-सूचियों को फिर से प्राप्त करने की आवश्यकता होगी जब वे अगली बार एक्सेस हो जाएं]।
सुपरकाट

2
जबकि मैं बनी बात से सहमत हूं, यह वास्तव में मेरी आत्मा को फाड़ देता है, किसी को डिजाइन सलाह देने और एक व्यापार सूची में एक सार्वजनिक सूची और सेटर के साथ एक ठोस सूची <टी> का खुलासा करने का सुझाव देने के लिए :(
सारा

38

डिजाइन> कार्यान्वयन

आपके द्वारा बताए गए तरीके और गुण एक डिजाइन निर्णय है। आपको कौन सा आधार वर्ग विरासत में मिला है, एक कार्यान्वयन विवरण है। मुझे लगता है कि यह एक कदम वापस लेने के लायक है।

ऑब्जेक्ट डेटा और व्यवहार का एक संग्रह है।

तो आपके पहले प्रश्न होने चाहिए:

  • मैं जो मॉडल बना रहा हूं उसमें यह ऑब्जेक्ट क्या डेटा शामिल करता है?
  • उस मॉडल में यह वस्तु किस व्यवहार को प्रदर्शित करती है?
  • भविष्य में यह कैसे बदल सकता है?

इस बात को ध्यान में रखें कि वंशानुक्रम का अर्थ "आइसा" (ए) संबंध है, जबकि रचना का अर्थ "ए" (हैसा) संबंध है। अपनी स्थिति में अपनी स्थिति के लिए सही चुनें, ध्यान में रखते हुए जहां चीजें आपके आवेदन के विकसित होने पर जा सकती हैं।

ठोस प्रकारों में सोचने से पहले इंटरफेस में विचार करें, क्योंकि कुछ लोगों को इस तरह से अपने दिमाग को "डिजाइन मोड" में रखना आसान लगता है।

यह ऐसा कुछ नहीं है जो हर कोई इस स्तर पर दिन-प्रतिदिन के कोडिंग में सचेत रूप से करता है। लेकिन अगर आप इस तरह के विषय को कम कर रहे हैं, तो आप डिजाइन वाटर में चल रहे हैं। इससे अवगत होना मुक्तिदायक हो सकता है।

डिजाइन विशिष्टताओं पर विचार करें

MSDN या Visual Studio पर सूची <T> और IList <T> देखें। देखें कि वे किन तरीकों और गुणों को उजागर करते हैं। क्या ये तरीके सभी को ऐसे लगते हैं, जैसे कोई व्यक्ति आपके विचार में किसी फ़ुटबॉल से करना चाहेगा?

क्या फ़ुटबॉलइम.रियर्स () आपके लिए मायने रखता है? क्या फ़ुटबॉलटेम.कॉनवर्ट ऑल <टुटपुट> () कुछ वैसा ही दिखता है जैसा आप चाहते हैं?

यह एक ट्रिक प्रश्न नहीं है; जवाब वास्तव में "हाँ" हो सकता है। यदि आप सूची <खिलाड़ी> या IList <खिलाड़ी> को लागू करते हैं, तो आप उनके साथ अटक जाते हैं; यदि यह आपके मॉडल के लिए आदर्श है, तो इसे करें।

यदि आप हाँ तय करते हैं, तो यह समझ में आता है, और आप चाहते हैं कि आपकी वस्तु खिलाड़ियों के संग्रह / सूची (व्यवहार) के रूप में व्यवहार्य हो, और आप इसलिए ICollection या IList को लागू करना चाहते हैं, हर तरह से। कल्पना की दृष्टि से:

class FootballTeam : ... ICollection<Player>
{
    ...
}

यदि आप चाहते हैं कि आपकी वस्तु खिलाड़ियों (डेटा) का एक संग्रह / सूची में शामिल हो, और आप चाहते हैं कि संग्रह या सूची एक संपत्ति या सदस्य हो, तो हर तरह से। कल्पना की दृष्टि से:

class FootballTeam ...
{
    public ICollection<Player> Players { get { ... } }
}

आप महसूस कर सकते हैं कि आप चाहते हैं कि लोग केवल खिलाड़ियों के सेट को गिनने में सक्षम हों, बजाय उन्हें गिनने, उन्हें जोड़ने या हटाने के। IEnumerable <Player> विचार करने के लिए एक पूरी तरह से वैध विकल्प है।

आप महसूस कर सकते हैं कि इनमें से कोई भी इंटरफेस आपके मॉडल में बिल्कुल भी उपयोगी नहीं है। यह कम संभावना है (IEnumerable <T> कई स्थितियों में उपयोगी है) लेकिन यह अभी भी संभव है।

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

कार्यान्वयन के लिए आगे बढ़ें

एक बार जब आप डेटा और व्यवहार के बारे में फैसला कर लेते हैं, तो आप कार्यान्वयन के बारे में निर्णय ले सकते हैं। इसमें शामिल हैं कि कौन सी ठोस कक्षाएं आप विरासत या रचना के माध्यम से निर्भर करते हैं।

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

ए थॉट एक्सपेरिमेंट

एक कृत्रिम उदाहरण: जैसा कि दूसरों ने उल्लेख किया है, एक टीम हमेशा "सिर्फ" खिलाड़ियों का संग्रह नहीं होती है। क्या आप टीम के लिए मैच स्कोर का संग्रह बनाए रखते हैं? क्या टीम आपके मॉडल में क्लब के साथ विनिमेय है? यदि ऐसा है, और यदि आपकी टीम खिलाड़ियों का आइसा संग्रह है, तो शायद यह स्टाफ का और / या स्कोर का संग्रह भी है। फिर आप के साथ अंत:

class FootballTeam : ... ICollection<Player>, 
                         ICollection<StaffMember>,
                         ICollection<Score>
{
    ....
}

डिजाइन के बावजूद, इस बिंदु पर C # में आप सूची से इन सभी को लागू करने में सक्षम नहीं होंगे <T> वैसे भी, क्योंकि C # "केवल" एकल वंशानुक्रम का समर्थन करता है। (यदि आपने C ++ में इस कुरूपता की कोशिश की है, तो आप इसे एक अच्छी बात मान सकते हैं।) एक संग्रह को विरासत के माध्यम से और एक को रचना के माध्यम से लागू करने से गंदा महसूस होने की संभावना है । और जब तक आप ILIst <Player> .Count और IList <StaffMember> .Count इत्यादि लागू नहीं करते हैं, तब तक गिनती जैसे गुण उपयोगकर्ताओं के लिए भ्रमित हो जाते हैं, और फिर वे भ्रमित होने के बजाय केवल दर्दनाक होते हैं। जहाँ यह जा रहा है वहां आप देख सकते हैं; आंत इस भावना के नीचे सोच रहा है अच्छी तरह से आपको बता सकता है कि यह इस दिशा में सिर के लिए गलत लगता है (और सही या गलत तरीके से, आपके सहकर्मी भी अगर आप इसे इस तरह से लागू कर सकते हैं!)

लघु उत्तर (बहुत देर से)

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


34

सबसे पहले, यह प्रयोज्य के साथ करना है। यदि आप वंशानुक्रम का उपयोग करते हैं, तो Teamवर्ग व्यवहार (विधियों) को उजागर करेगा जो विशुद्ध रूप से ऑब्जेक्ट हेरफेर के लिए डिज़ाइन किए गए हैं। उदाहरण के लिए, AsReadOnly()या CopyTo(obj)तरीके टीम ऑब्जेक्ट के लिए कोई मतलब नहीं रखते हैं। AddRange(items)विधि के बजाय आप शायद अधिक वर्णनात्मक AddPlayers(players)विधि चाहते हैं ।

आप इस तरह के रूप LINQ उपयोग करने के लिए, एक सामान्य इंटरफ़ेस को लागू करना चाहते हैं ICollection<T>या IEnumerable<T>अधिक मतलब होगा।

जैसा कि उल्लेख किया गया है, रचना इसके बारे में जाने का सही तरीका है। बस एक निजी चर के रूप में खिलाड़ियों की सूची को लागू करें।


30

एक फुटबॉल टीम फुटबॉल खिलाड़ियों की सूची नहीं है। एक फुटबॉल टीम फुटबॉल खिलाड़ियों की सूची से बना है !

यह तार्किक रूप से गलत है:

class FootballTeam : List<FootballPlayer> 
{ 
    public string TeamName; 
    public int RunningTotal 
}

और यह सही है:

class FootballTeam 
{ 
    public List<FootballPlayer> players
    public string TeamName; 
    public int RunningTotal 
}

19
यह क्यों नहीं समझाता है । ओपी जानता है कि अधिकांश अन्य प्रोग्रामर इस तरह से महसूस करते हैं, वह सिर्फ यह नहीं समझता कि यह महत्वपूर्ण क्यों है। यह केवल प्रश्न में पहले से ही जानकारी प्रदान कर रहा है।
सर्व

2
यह पहली चीज है, जिसके बारे में मैंने भी सोचा था कि कैसे उसका डेटा सिर्फ गलत तरीके से तैयार किया गया था। तो इसका कारण है, आपका डेटा मॉडल गलत है।
rball

3
सूची से विरासत में क्यों नहीं? क्योंकि वह अधिक विशिष्ट प्रकार की सूची नहीं चाहता है।
मौरो सेम्पिट्रो

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

1
एनकैप्सुलेशन प्रश्न का बिंदु नहीं है। यदि आप उस प्रकार को अधिक विशिष्ट तरीके से व्यवहार नहीं करना चाहते हैं तो मैं एक प्रकार का विस्तार नहीं करने पर ध्यान केंद्रित करता हूं। उन क्षेत्रों को c # में autoproperties होना चाहिए और अन्य भाषाओं में विधियाँ प्राप्त / सेट करनी चाहिए लेकिन यहाँ इस संदर्भ में जो पूरी तरह से
अतिश्योक्तिपूर्ण है

28

ये संदर्भ पर निर्भर करता है

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

अस्पष्ट शब्दार्थ

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

कक्षाएं एक्स्टेंसिबल हैं

जब आप केवल एक सदस्य (उदाहरण के लिए IList activePlayers) के साथ एक वर्ग का उपयोग कर रहे हैं, तो आप संदर्भ को स्पष्ट करने के लिए सदस्य के नाम (और इसके अतिरिक्त) का उपयोग कर सकते हैं। जब अतिरिक्त संदर्भ होते हैं, तो आप केवल एक अतिरिक्त सदस्य जोड़ते हैं।

कक्षाएं अधिक जटिल हैं

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

निष्कर्ष / विचार

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

IList<Player> footballTeam = ...

F # का उपयोग करते समय, एक प्रकार का संक्षिप्त नाम बनाना भी ठीक हो सकता है:

type FootballTeam = IList<Player>

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


27

मुझे आपके प्रश्न को फिर से लिखना चाहिए। इसलिए आप इस विषय को एक अलग दृष्टिकोण से देख सकते हैं।

जब मुझे एक फुटबॉल टीम का प्रतिनिधित्व करने की आवश्यकता होती है, तो मैं समझता हूं कि यह मूल रूप से एक नाम है। जैसे: "द ईगल्स"

string team = new string();

फिर बाद में मुझे एहसास हुआ कि टीमों में भी खिलाड़ी होते हैं।

मैं केवल स्ट्रिंग प्रकार का विस्तार क्यों नहीं कर सकता ताकि यह खिलाड़ियों की सूची भी रखे?

समस्या में प्रवेश की आपकी बात मनमानी है। यह सोचने की कोशिश करें कि किसी टीम के पास क्या (गुण) हैं, न कि वह क्या है

ऐसा करने के बाद, आप देख सकते हैं कि क्या यह अन्य वर्गों के साथ संपत्ति साझा करता है। और वंशानुक्रम के बारे में सोचो।


1
यह एक अच्छी बात है - टीम सिर्फ एक नाम के रूप में सोच सकती है। हालांकि, अगर मेरा आवेदन खिलाड़ियों के कार्यों के साथ काम करना है, तो यह सोच थोड़ी कम स्पष्ट है। वैसे भी, ऐसा लगता है कि मुद्दा अंत में रचना बनाम विरासत में आता है।
१०:३४

6
यह देखने के लिए एक मेधावी तरीका है। एक साइड नोट कृपया इस पर विचार करें: धन का एक आदमी कई फुटबॉल टीमों का मालिक है, वह उपहार के रूप में एक दोस्त को देता है, दोस्त टीम का नाम बदलता है, कोच को आग लगाता है, और सभी खिलाड़ियों को बदल देता है। दोस्तों की टीम ग्रीन पर पुरुषों की टीम से मिलती है और जैसा कि पुरुषों की टीम हार रही है वह कहता है "मुझे विश्वास नहीं हो रहा है कि आप मुझे उस टीम से हरा रहे हैं जो मैंने आपको दी थी!" क्या आदमी सही है? आप इसे कैसे जांचेंगे?
user1852503

20

सिर्फ इसलिए कि मुझे लगता है कि अन्य उत्तर बहुत अधिक एक स्पर्शरेखा पर चले जाते हैं कि क्या एक फुटबॉल टीम "-ए" List<FootballPlayer>या "है-ए" है List<FootballPlayer>, जो वास्तव में लिखित रूप में इस प्रश्न का उत्तर नहीं देता है।

ओपी मुख्य रूप से विरासत के लिए दिशानिर्देशों पर स्पष्टीकरण मांगता है List<T>:

एक गाइडलाइन कहती है कि आपको इससे विरासत में नहीं लेना चाहिए List<T>। क्यों नहीं?

क्योंकि List<T>कोई वर्चुअल तरीका नहीं है। यह आपके अपने कोड में एक समस्या से कम है, क्योंकि आप आमतौर पर कार्यान्वयन को अपेक्षाकृत कम दर्द के साथ बदल सकते हैं - लेकिन एक सार्वजनिक एपीआई में यह बहुत बड़ा सौदा हो सकता है।

सार्वजनिक एपीआई क्या है और मुझे इसकी देखभाल क्यों करनी चाहिए?

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

यदि मेरी वर्तमान परियोजना में इस सार्वजनिक एपीआई के होने की संभावना नहीं है और क्या मैं इस दिशानिर्देश को सुरक्षित रूप से अनदेखा कर सकता हूं? अगर मुझे सूची से विरासत मिली और यह पता चला कि मुझे सार्वजनिक एपीआई की आवश्यकता है, तो मुझे क्या कठिनाइयाँ होंगी?

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

यदि आप भविष्य में एक सार्वजनिक एपीआई जोड़ते हैं, तो आपको या तो अपने एपीआई को अपने कार्यान्वयन से बाहर करना होगा (अपने List<T>सीधे को उजागर नहीं करके ) या भविष्य के संभावित दर्द के साथ दिशानिर्देशों का उल्लंघन करना होगा जो आपको मजबूर करता है।

इससे भी फर्क क्यों पड़ता है? एक सूची एक सूची है। क्या संभवतः बदल सकता है? मैं संभवतः क्या बदलना चाहता हूं?

संदर्भ पर निर्भर करता है, लेकिन जब से हम FootballTeamएक उदाहरण के रूप में उपयोग कर रहे हैं - कल्पना करें कि आप जोड़ नहीं सकते हैं FootballPlayerअगर यह टीम को वेतन कैप पर जाने का कारण बनेगा। जोड़ने का एक संभावित तरीका जो कुछ इस तरह होगा:

 class FootballTeam : List<FootballPlayer> {
     override void Add(FootballPlayer player) {
        if (this.Sum(p => p.Salary) + player.Salary > SALARY_CAP)) {
          throw new InvalidOperationException("Would exceed salary cap!");
        }
     }
 }

आह ... लेकिन आप नहीं कर सकते override Addक्योंकि यह नहीं हैvirtual (प्रदर्शन कारणों के लिए) नहीं है।

यदि आप एक एप्लिकेशन में हैं (जो, मूल रूप से, इसका मतलब है कि आप और आपके सभी कॉलर्स एक साथ संकलित किए गए हैं) तो आप अब IList<T>किसी भी संकलित त्रुटियों का उपयोग करने और ठीक करने के लिए बदल सकते हैं :

 class FootballTeam : IList<FootballPlayer> {
     private List<FootballPlayer> Players { get; set; }

     override void Add(FootballPlayer player) {
        if (this.Players.Sum(p => p.Salary) + player.Salary > SALARY_CAP)) {
          throw new InvalidOperationException("Would exceed salary cap!");
        }
     }
     /* boiler plate for rest of IList */
 }

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

टीएल; डीआर - दिशानिर्देश सार्वजनिक एपीआई के लिए हैं। निजी एपीआई के लिए, आप जो चाहते हैं वह करें।


18

लोगों को कहने की अनुमति देता है

myTeam.subList(3, 5);

कोई मतलब नहीं है? यदि नहीं तो यह एक सूची नहीं होनी चाहिए।


3
अगर आप इसे कहते हैंmyTeam.subTeam(3, 5);
सैम लेच

3
@SamLeach मान लें कि यह सच है, तो आपको अभी भी रचना की आवश्यकता होगी, विरासत की नहीं। जैसा कि अब और subListभी नहीं लौटेगा Team
क्रंचर

1
इसने मुझे किसी भी अन्य उत्तर की तुलना में अधिक आश्वस्त किया। +1
फायरक्यूबेज़

16

यह आपके "टीम" ऑब्जेक्ट के व्यवहार पर निर्भर करता है । यदि यह एक संग्रह की तरह व्यवहार करता है, तो इसे पहले एक सादे सूची के साथ प्रस्तुत करना ठीक हो सकता है। तब आप यह देखना शुरू कर सकते हैं कि आप सूची में पुनरावृत्ति करने वाले कोड को दोहराते रहें; इस बिंदु पर आपके पास एक फुटबॉलटेम ऑब्जेक्ट बनाने का विकल्प है जो खिलाड़ियों की सूची को लपेटता है। फुटबॉलटेम वर्ग उन सभी कोड के लिए घर बन जाता है जो खिलाड़ियों की सूची पर आधारित होते हैं।

यह मेरा कोड अनावश्यक रूप से क्रिया करता है। मुझे अब सिर्फ my_team.Count के बजाय my_team.Players.ount को कॉल करना होगा। शुक्र है, सी # के साथ, मैं अनुक्रमित को पारदर्शी बनाने के लिए इंडेक्सर्स को परिभाषित कर सकता हूं, और आंतरिक सूची के सभी तरीकों को आगे बढ़ा सकता हूं ... लेकिन यह बहुत कोड है! मुझे उस काम के लिए क्या मिलेगा?

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

यह सिर्फ सादा मतलब नहीं है। एक फुटबॉल टीम के पास खिलाड़ियों की सूची नहीं है। यह खिलाड़ियों की सूची है। आप यह नहीं कहते "जॉन मैकफुटबॉलर SomeTeam के खिलाड़ियों में शामिल हो गया है"। आप कहते हैं "जॉन SomeTeam में शामिल हो गए हैं"। आप "स्ट्रिंग के पात्रों" के लिए एक पत्र नहीं जोड़ते हैं, आप एक स्ट्रिंग में एक पत्र जोड़ते हैं। आप किसी पुस्तकालय की पुस्तकों में पुस्तक नहीं जोड़ते हैं, आप पुस्तकालय में पुस्तक जोड़ते हैं।

बिल्कुल :) आप कहेंगे फुटबॉलटीम.एड.डॉन (जॉन), फुटबॉलटाइम नहीं। लिस्ट.एडीडी (जॉन)। आंतरिक सूची दिखाई नहीं देगी।


1
ओपी यह समझना चाहता है कि मॉडल की असलियत कैसी है लेकिन फिर एक फुटबॉल टीम को फुटबॉल खिलाड़ियों की सूची के रूप में परिभाषित किया जाता है (जो कि गलत तरीके से गलत है)। यही समस्या है। मेरी राय में कोई अन्य तर्क उसे गुमराह कर रहा है।
मौरो सेम्पीटरो

3
मैं असहमत हूं कि खिलाड़ियों की सूची वैचारिक रूप से गलत है। जरुरी नहीं। जैसा कि किसी और ने इस पेज में लिखा है, "सभी मॉडल गलत हैं, लेकिन कुछ उपयोगी हैं"
xpmatteo

सही मॉडल प्राप्त करने के लिए कठिन हैं, एक बार वे उपयोगी हैं। यदि किसी मॉडल का दुरुपयोग किया जा सकता है तो यह वैचारिक रूप से गलत है। stackoverflow.com/a/21706411/711061
मौरो सेम्पीटरो

15

यहाँ बहुत सारे उत्कृष्ट उत्तर हैं, लेकिन मैं कुछ ऐसी चीज़ों को छूना चाहता हूँ, जिनका मैंने उल्लेख नहीं किया है: ऑब्जेक्ट ओरिएंटेड डिज़ाइन ऑब्जेक्ट्स को सशक्त बनाने के बारे में है

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

जब आप विरासत में लेते हैं List, तो अन्य सभी वस्तुएँ आपको एक सूची के रूप में देख सकती हैं। खिलाड़ियों को जोड़ने और हटाने के तरीकों के लिए उनकी सीधी पहुंच है। और आप अपना नियंत्रण खो देंगे; उदाहरण के लिए:

मान लीजिए कि आप किसी खिलाड़ी के सेवानिवृत्त होने, इस्तीफा देने या निकाल दिए जाने के बारे में जानकर अंतर करना चाहते हैं। आप एक RemovePlayerविधि लागू कर सकते हैं जो एक उपयुक्त इनपुट एनम लेता है। हालाँकि, इनहेरिट करके List, आप सीधे पहुँच को रोकने में असमर्थ होंगे Remove, RemoveAllऔर यहाँ तक कि Clear। नतीजतन, आप वास्तव में कर दिया है पास कोई अधिकार नहीं अपने FootballTeamवर्ग।


एनकैप्सुलेशन पर अतिरिक्त विचार ... आपने निम्नलिखित चिंता जताई:

यह मेरा कोड अनावश्यक रूप से क्रिया करता है। मुझे अब सिर्फ my_team.Count के बजाय my_team.Players.ount को कॉल करना होगा।

आप सही हैं, कि सभी ग्राहकों को आपकी टीम का उपयोग करने के लिए अनावश्यक रूप से क्रिया करनी होगी। हालांकि, यह समस्या इस तथ्य की तुलना में बहुत कम है कि आप List Playersसभी और विविधताओं से अवगत हैं, ताकि वे आपकी सहमति के बिना आपकी टीम के साथ जुड़ सकें।

आप कहते हैं:

यह सिर्फ सादा मतलब नहीं है। एक फुटबॉल टीम के पास खिलाड़ियों की सूची नहीं है। यह खिलाड़ियों की सूची है। आप नहीं कहते हैं "जॉन मैकफुटबॉलर SomeTeam के खिलाड़ियों में शामिल हो गया है"। आप कहते हैं "जॉन SomeTeam में शामिल हो गए हैं"।

आप पहले बिट के बारे में गलत हैं: 'सूची' शब्द को छोड़ दें, और यह वास्तव में स्पष्ट है कि एक टीम में खिलाड़ी होते हैं।
हालांकि, आपने दूसरे के साथ सिर पर नाखून मारा। आप ग्राहकों को फोन नहीं करना चाहते हैं ateam.Players.Add(...)। आप उन्हें फोन करना चाहते हैं ateam.AddPlayer(...)। और आपका कार्यान्वयन संभवतः (अन्य चीजों के बीच) Players.Add(...)आंतरिक रूप से कॉल करेगा ।


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


12

डेटा संरचना का प्रतिनिधित्व करने का सही C # तरीका क्या है ...

रिमेबर, "सभी मॉडल गलत हैं, लेकिन कुछ उपयोगी हैं।" - जॉर्ज ईपी बॉक्स

कोई "सही तरीका" नहीं है, केवल एक उपयोगी है।

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

- संपादित

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

- संस्करण 2

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

दूसरी ओर, मेरा मानना ​​है कि सीमित संख्या में ऐसे मामले हैं जहाँ केवल सूची से विरासत प्राप्त करना उपयोगी है। जैसा कि मैंने पिछले संस्करण में लिखा था, यह निर्भर करता है। प्रत्येक मामले का उत्तर ज्ञान, अनुभव और व्यक्तिगत प्राथमिकताओं दोनों से काफी प्रभावित होता है।

उत्तर के बारे में अधिक सटीक सोचने में मेरी मदद करने के लिए @kai का धन्यवाद।


मेरा सबसे अच्छा जवाब होगा ... यह निर्भर करता है। सूची से इनहेरिट करना इस वर्ग के ग्राहकों को उन तरीकों को उजागर करेगा, जिन्हें उजागर नहीं किया जाना चाहिए, मुख्यतः क्योंकि फुटबॉलटम एक व्यावसायिक इकाई की तरह दिखता है। मुझे नहीं पता कि मुझे इस उत्तर को संपादित करना चाहिए या किसी अन्य विचार को पोस्ट करना चाहिए?
आर्टुरोटेना

2
"इन ए से विरासत में मिलीList बिट" इस वर्ग के ग्राहकों को उन तरीकों के बारे में बताएगी, जिन्हें उजागर नहीं किया जाना चाहिए "ठीक वही है जो Listएक निरपेक्ष नंबर से विरासत में मिला है । एक बार उजागर होने के बाद, वे धीरे-धीरे समय के साथ दुरुपयोग और गलत उपयोग करते हैं। "आर्थिक रूप से विकसित" होने से अब समय की बचत आसानी से भविष्य में खो जाने वाली बचत को दस गुना कर सकती है: दुर्व्यवहारों को डीबग करना और अंततः विरासत को ठीक करने के लिए फिर से तैयार करना। YAGNI सिद्धांत को भी अर्थ के रूप में माना जा सकता है: आप उन सभी तरीकों की आवश्यकता नहीं कर सकते हैं List, इसलिए उन्हें उजागर न करें।
मोहभंग हुआ

3
"ओवर-इंजीनियर न करें। जितना कम कोड आप लिखते हैं, उतना कम कोड आपको डीबग करने की आवश्यकता होगी।" <- मुझे लगता है कि यह भ्रामक है। वंशानुक्रम पर एनकैप्सुलेशन और कंपोजिशन ओवर-इंजीनियरिंग नहीं है और इससे डिबगिंग की अधिक आवश्यकता नहीं होती है। एनकैप्सुलेट करके आप उन तरीकों की संख्या को सीमित कर रहे हैं जो ग्राहक आपकी कक्षा का उपयोग (और दुरुपयोग) कर सकते हैं और इस प्रकार आपके पास कम प्रवेश बिंदु हैं जिन्हें परीक्षण और इनपुट सत्यापन की आवश्यकता है। इनहेरिटिंग Listक्योंकि यह त्वरित और आसान है और इस तरह कम बग को बढ़ावा मिलेगा, यह गलत है, यह सिर्फ खराब डिजाइन है और खराब डिजाइन "ओवर इंजीनियरिंग" की तुलना में बहुत अधिक बग की ओर जाता है।
सारा

@kai मैं आपकी हर बात से सहमत हूँ। मुझे ईमानदारी से याद नहीं है कि मैं "ओवर-इंजीनियर" टिप्पणी पर क्या उल्लेख कर रहा था। ओटीओएच, मेरा मानना ​​है कि सीमित संख्या में मामले हैं जहां केवल सूची से वार करना उपयोगी है। जैसा कि मैंने बाद के संस्करण में लिखा था, यह निर्भर करता है। प्रत्येक मामले का उत्तर ज्ञान, अनुभव और व्यक्तिगत प्राथमिकताओं दोनों से काफी प्रभावित होता है। जैसे जीवन में सब कुछ। ;-)
आर्टुरोटेना

11

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

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


9

मेरा गंदा रहस्य: मुझे परवाह नहीं है कि लोग क्या कहते हैं, और मैं इसे करता हूं। .NET फ्रेमवर्क "XxxxCollection" (मेरे मुख्य उदाहरण के लिए UIElementCollection) के साथ फैला हुआ है।

तो मुझे क्या कहना बंद हो जाता है:

team.Players.ByName("Nicolas")

जब मुझे इससे बेहतर मिलेगा

team.ByName("Nicolas")

इसके अलावा, मेरा प्लेयरकॉलक्शन अन्य वर्ग द्वारा उपयोग किया जा सकता है, जैसे "क्लब" बिना किसी कोड दोहराव के।

club.Players.ByName("Nicolas")

कल की सर्वोत्तम प्रथाएं, शायद कल की नहीं हो सकती हैं। अधिकांश सर्वोत्तम प्रथाओं के पीछे कोई कारण नहीं है, अधिकांश समुदाय के बीच केवल व्यापक समझौते हैं। समुदाय से यह पूछने के बजाय कि क्या यह आपको दोषी ठहराएगा जब आप ऐसा करते हैं कि आप खुद से पूछें कि क्या अधिक पठनीय और रखरखाव योग्य है?

team.Players.ByName("Nicolas") 

या

team.ByName("Nicolas")

वास्तव में। क्या तुम्हे कोई शक है? अब शायद आपको अन्य तकनीकी बाधाओं के साथ खेलने की ज़रूरत है जो आपको अपने वास्तविक उपयोग के मामले में सूची <T> का उपयोग करने से रोकते हैं। लेकिन एक बाधा नहीं है जो मौजूद नहीं होनी चाहिए। यदि Microsoft ने दस्तावेज़ का क्यों नहीं किया, तो यह निश्चित रूप से एक "सर्वोत्तम अभ्यास" है जो कहीं से भी नहीं आ रहा है।


9
हालांकि जब उचित हो तो स्वीकृत ज्ञान को चुनौती देने के लिए साहस और पहल करना महत्वपूर्ण है, मुझे लगता है कि पहले यह समझना बुद्धिमानी है कि स्वीकार किए गए ज्ञान को स्वीकार करने से पहले क्यों स्वीकार किया गया है। -1 क्योंकि "उस दिशानिर्देश को अनदेखा करें!" "क्यों यह दिशानिर्देश मौजूद नहीं है?" संयोग से, समुदाय ने इस मामले में न केवल मुझे "दोषी ठहराया", बल्कि एक संतोषजनक स्पष्टीकरण प्रदान किया जो मुझे समझाने में सफल रहा।
13

3
यह वास्तव में है, जब कोई स्पष्टीकरण नहीं किया जाता है, तो आपका एकमात्र तरीका सीमा को धक्का दे रहा है और परीक्षण से उल्लंघन का डर नहीं है। अभी। अपने आप से पूछें, भले ही सूची <टी> एक अच्छा विचार नहीं था। लिस्ट <T> से कलेक्शन <T> में इनहेरिटेंस को बदलने में कितना दर्द होगा? एक अनुमान: मंच पर पोस्टिंग की तुलना में कम समय, जो भी आपके कोड की लंबाई रिफैक्टरिंग टूल के साथ है। अब यह एक अच्छा सवाल है, लेकिन व्यावहारिक नहीं है।
निकोलस डोरियर

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

2
team.ByName("Nicolas")मतलब "Nicolas"टीम का नाम है।
सैम लीच

1
"एक बाधा नहीं है जो मौजूद नहीं होनी चाहिए" एयू गर्भनिरोधक, कुछ भी उजागर न करें जिसे आपके पास उजागर करने का एक अच्छा कारण नहीं है। यह शुद्धतावाद या अंधभक्ति नहीं है, न ही यह नवीनतम डिजाइन फैशन की प्रवृत्ति है। यह बेसिक ऑब्जेक्ट ओरिएंटेड डिज़ाइन 101, शुरुआती स्तर है। यह एक रहस्य नहीं है कि यह "नियम" क्यों मौजूद है, यह कई दशकों के अनुभव का परिणाम है।
सार

8

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


रेट्रोस्पेक्ट में, @EricLippert और अन्य लोगों के स्पष्टीकरण के बाद, आपने वास्तव में मेरे प्रश्न के एपीआई भाग के लिए एक शानदार जवाब दिया है - इसके अलावा आपने क्या कहा, यदि मैं करता हूं, तो class FootballTeam : List<FootballPlayers>मेरी कक्षा के उपयोगकर्ता मुझे बता पाएंगे ' मैं List<T>परावर्तन का उपयोग करके विरासत में मिला , List<T>जो कि एक फुटबॉल टीम के लिए समझ में नहीं आता है, और FootballTeamमें उपयोग करने में सक्षम है List<T>, इसलिए मैं ग्राहक (अनावश्यक रूप से) के लिए कार्यान्वयन विवरण प्रकट होगा ।
शानदार

7

जब वे कहते हैं List<T>"अनुकूलित" मुझे लगता है कि वे चाहते हैं कि इसका मतलब यह है कि इसमें आभासी तरीके जैसी विशेषताएं नहीं हैं जो थोड़ा अधिक महंगा हैं। तो समस्या यह है कि एक बार जब आप List<T>अपने सार्वजनिक एपीआई में उजागर होते हैं , तो आप व्यावसायिक नियमों को लागू करने या बाद में इसकी कार्यक्षमता को अनुकूलित करने की क्षमता को ढीला कर देते हैं। लेकिन यदि आप अपनी परियोजना के भीतर इस विरासत वाले वर्ग को आंतरिक के रूप में उपयोग कर रहे हैं (जैसा कि आपके ग्राहकों / भागीदारों / एपीआई के रूप में अन्य टीमों के हजारों लोगों के सामने संभावित रूप से सामने आता है) तो यह ठीक हो सकता है यदि यह आपका समय बचाता है और यह वह कार्यक्षमता है जिसे आप चाहते हैं नकल। विरासत से लाभList<T> है कि आप बहुत सारे डम्पर रैपर कोड को खत्म कर देते हैं जो कि भविष्य में कभी भी कस्टमाइज़ नहीं किए जा सकते हैं। यदि आप चाहते हैं कि आपकी कक्षा स्पष्ट रूप से ठीक उसी शब्दार्थ के रूप में होList<T> अपने एपीआई के जीवन के लिए तो यह भी ठीक हो सकता है।

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


4

हालांकि इनमें से अधिकांश जवाबों की जटिल तुलना नहीं है, लेकिन मैं इस स्थिति से निपटने के लिए अपने तरीके को साझा करना चाहूंगा। विस्तृत करके IEnumerable<T>, आप Teamसार्वजनिक रूप से सभी विधियों और गुणों को उजागर किए बिना, अपनी कक्षा को Linq क्वेरी एक्सटेंशन का समर्थन करने की अनुमति दे सकते हैं List<T>

class Team : IEnumerable<Player>
{
    private readonly List<Player> playerList;

    public Team()
    {
        playerList = new List<Player>();
    }

    public Enumerator GetEnumerator()
    {
        return playerList.GetEnumerator();
    }

    ...
}

class Player
{
    ...
}

3

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

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

छोटे ऐप्स के लिए, आप दूसरी, कम सख्त भाषा चुनने पर भी विचार कर सकते हैं। रूबी, जावास्क्रिप्ट - कुछ भी जो आपको कम कोड लिखने की अनुमति देता है।


3

मैं सिर्फ उस बर्ट्रेंड मेयर को जोड़ना चाहता था, जो अनुबंध के द्वारा एफिल और डिजाइन के आविष्कारक थे, बिना पलक झपकाए इतने Teamसे विरासत में मिले List<Player>

अपनी पुस्तक, ऑब्जेक्ट-ओरिएंटेड सॉफ्टवेयर कंस्ट्रक्शन में , वह एक जीयूआई प्रणाली के कार्यान्वयन पर चर्चा करता है जहां आयताकार खिड़कियों में बच्चे की खिड़कियां हो सकती हैं। वह बस Windowदोनों से विरासत में मिला है Rectangleऔर Tree<Window>कार्यान्वयन का पुन: उपयोग करता है।

हालाँकि, C # Eiffel नहीं है। उत्तरार्द्ध कई उत्तराधिकार और सुविधाओं के नामकरण का समर्थन करता है । C # में, जब आप उपवर्ग करते हैं, तो आप इंटरफ़ेस और इम्प्लांटेशन दोनों को प्राप्त करते हैं। आप कार्यान्वयन को ओवरराइड कर सकते हैं, लेकिन कॉलिंग सम्मेलनों को सीधे सुपरक्लास से कॉपी किया जाता है। एफिल में, हालांकि, आप सार्वजनिक तरीकों के नाम है, तो आप नाम बदल सकते हैं संशोधित कर सकते हैं Addऔर Removeकरने के लिए Hireऔर Fireअपने में Team। यदि कोई उदाहरण Teamवापस करने के लिए है List<Player>, तो कॉलर उपयोग करेगा Addऔर Removeउसे संशोधित करेगा, लेकिन आपके वर्चुअल तरीके Hireऔर Fireकहा जाएगा।


1
यहाँ समस्या एकाधिक वंशानुक्रम, मिश्रण (आदि) या उनकी अनुपस्थिति से निपटने के लिए नहीं है। किसी भी भाषा में, यहां तक ​​कि मानव भाषा में भी एक टीम लोगों की सूची नहीं है, बल्कि लोगों की सूची से बना है। यह एक अमूर्त अवधारणा है। यदि बर्ट्रेंड मेयर या कोई भी व्यक्ति उप-सूचीबद्ध करके एक टीम का प्रबंधन करता है तो गलत कर रहा है। यदि आपको अधिक विशिष्ट प्रकार की सूची चाहिए, तो आपको एक सूची को उप-वर्ग करना चाहिए। आशा है आप सहमत होंगे।
मौरो सेम्पीटरो

1
यह इस बात पर निर्भर करता है कि आपको क्या विरासत में मिला है। अपने आप में, यह एक सार ऑपरेशन है, इसका मतलब यह नहीं है कि दो वर्ग "एक विशेष प्रकार का" संबंध हैं, भले ही यह मुख्यधारा की व्याख्या है। हालाँकि, इनहेरिटेंस को कार्यान्वयन पुन: उपयोग के लिए एक तंत्र के रूप में माना जा सकता है यदि भाषा डिजाइन इसका समर्थन करता है, भले ही रचना आजकल संक्षिप्त विकल्प है।
एलेक्सी

2

मुझे लगता है कि मैं आपके सामान्यीकरण से सहमत नहीं हूं। एक टीम सिर्फ खिलाड़ियों का संग्रह नहीं है। एक टीम के पास इसके बारे में बहुत अधिक जानकारी है - नाम, प्रतीक, प्रबंधन / व्यवस्थापक कर्मचारियों का संग्रह, कोचिंग चालक दल का संग्रह, फिर खिलाड़ियों का संग्रह। ठीक से, आपके फ़ुटबॉलटैम वर्ग में 3 संग्रह होने चाहिए और न ही स्वयं एक संग्रह होना चाहिए; अगर यह वास्तविक दुनिया को ठीक से मॉडल करना है।

आप एक PlayerCollection वर्ग पर विचार कर सकते हैं जो विशिष्ट StringCollection की तरह कुछ अन्य सुविधाएं प्रदान करता है - जैसे कि वस्तुओं को आंतरिक स्टोर से हटाने या हटाने से पहले सत्यापन और जांच।

शायद, एक PlayerCollection बेटर्स की धारणा आपके पसंदीदा दृष्टिकोण के अनुरूप है?

public class PlayerCollection : Collection<Player> 
{ 
}

और फिर फुटबॉलटीम इस तरह दिख सकता है:

public class FootballTeam 
{ 
    public string Name { get; set; }
    public string Location { get; set; }

    public ManagementCollection Management { get; protected set; } = new ManagementCollection();

    public CoachingCollection CoachingCrew { get; protected set; } = new CoachingCollection();

    public PlayerCollection Players { get; protected set; } = new PlayerCollection();
}

2

कक्षाओं पर प्राथमिकताएं

कक्षाओं को कक्षाओं से निकलने से बचना चाहिए और इसके बजाय आवश्यक न्यूनतम इंटरफेस को लागू करना चाहिए।

वंशानुक्रम में विघटन होता है

कक्षाओं से छूटना अतिक्रमण को तोड़ता है :

  • आपके संग्रह को कैसे कार्यान्वित किया जाता है, इसके बारे में आंतरिक विवरण को उजागर करता है
  • एक इंटरफ़ेस (सार्वजनिक कार्यों और गुणों का सेट) घोषित करता है जो उचित नहीं हो सकता है

अन्य बातों के अलावा यह आपके कोड को फिर से भरना कठिन बना देता है।

कक्षाएं एक कार्यान्वयन विवरण हैं

कक्षाएं एक कार्यान्वयन विवरण है जिसे आपके कोड के अन्य भागों से छिपाया जाना चाहिए। संक्षेप System.Listमें एक अमूर्त डेटा प्रकार का एक विशिष्ट कार्यान्वयन है, जो अभी और भविष्य में उचित नहीं हो सकता है।

वैचारिक रूप से System.Listडेटा प्रकार को "सूची" कहा जाता है, यह एक लाल-हेरिंग का एक सा है। A System.List<T>एक उत्परिवर्तित आदेश संग्रह है जो तत्वों को जोड़ने, सम्मिलित करने और हटाने और तत्वों की संख्या प्राप्त करने या अनुक्रमणिका द्वारा तत्व को प्राप्त करने और स्थापित करने के लिए परिचालित O (1) परिचालनों का समर्थन करता है।

इंटरफ़ेस जितना छोटा होगा उतना अधिक लचीला कोड होगा

डेटा संरचना को डिज़ाइन करते समय, इंटरफ़ेस जितना सरल होता है, उतना ही लचीला कोड होता है। बस देखो कि इस प्रदर्शन के लिए LINQ कितना शक्तिशाली है।

इंटरफेसेस कैसे चुनें

जब आपको लगता है कि "सूची" आपको अपने आप से कहकर शुरू करनी चाहिए, "मुझे बेसबॉल खिलाड़ियों के संग्रह का प्रतिनिधित्व करने की आवश्यकता है"। तो मान लीजिए कि आप इसे एक कक्षा के साथ तय करते हैं। आपको पहले क्या करना चाहिए, यह तय करना है कि इस वर्ग को कितनी न्यूनतम मात्रा में इंटरफेस की आवश्यकता होगी।

कुछ सवाल जो इस प्रक्रिया को निर्देशित करने में मदद कर सकते हैं:

  • क्या मुझे गिनती करने की आवश्यकता है? यदि लागू करने पर विचार नहीं करते हैंIEnumerable<T>
  • क्या यह संग्रह आरंभ होने के बाद बदलने वाला है? अगर नहीं माना IReadonlyList<T>
  • क्या यह महत्वपूर्ण है कि मैं वस्तुओं को सूचकांक द्वारा एक्सेस कर सकता हूं? विचार करेंICollection<T>
  • क्या वह आदेश है जिसमें मैं संग्रह में आइटम जोड़ना महत्वपूर्ण हूं? शायद यह एक है ISet<T>?
  • यदि आप वास्तव में इन चीजों को चाहते हैं तो आगे बढ़ें और कार्यान्वित करें IList<T>

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

इस दृष्टिकोण को अपनाने से आप पाएंगे कि कोड पढ़ना, रिफलेक्टर और पुन: उपयोग करना आसान हो जाता है।

बॉयलरप्लेट से बचने के बारे में नोट्स

एक आधुनिक आईडीई में इंटरफेस को लागू करना आसान होना चाहिए। राइट क्लिक करें और "इम्प्लीमेंट इंटरफेस" चुनें। यदि आवश्यक हो तो एक सदस्य वर्ग के लिए कार्यान्वयन के सभी आगे।

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

आप छोटे इंटरफेस भी डिज़ाइन कर सकते हैं जो आपके एप्लिकेशन के लिए समझ में आते हैं, और हो सकता है कि बस उन हेल्पर्स एक्सटेंशन के एक जोड़े को उन इंटरफेस को किसी अन्य व्यक्ति को मैप करने की ज़रूरत हो जो आपको चाहिए। यह वह दृष्टिकोण है जिसे मैंने LinqArray लाइब्रेरी केIArray लिए अपने स्वयं के इंटरफ़ेस में लिया था ।


2

क्रमबद्धता के साथ समस्या

एक पहलू याद आ रहा है। सूची <> से विरासत में मिली कक्षाएं XmlSerializer का उपयोग करके सही ढंग से क्रमबद्ध नहीं की जा सकती हैं । उस स्थिति में DataContractSerializer का उपयोग इसके बजाय किया जाना चाहिए, या स्वयं के क्रमबद्ध कार्यान्वयन की आवश्यकता है।

public class DemoList : List<Demo>
{
    // using XmlSerializer this properties won't be seralized:
    string AnyPropertyInDerivedFromList { get; set; }     
}

public class Demo
{
    // this properties will be seralized
    string AnyPropetyInDemo { get; set; }  
}

आगे पढ़ने: जब एक वर्ग सूची <> से विरासत में मिला है, तो XmlSerializer अन्य विशेषताओं को अनुक्रमित नहीं करता है


0

यह कब स्वीकार्य है?

एरिक लिपर्ट को उद्धृत करने के लिए:

जब आप एक तंत्र का निर्माण कर रहे हैं जो तंत्र का विस्तार करता List<T>है।

उदाहरण के लिए, आप AddRangeविधि की अनुपस्थिति से थक चुके हैं IList<T>:

public interface IMoreConvenientListInterface<T> : IList<T>
{
    void AddRange(IEnumerable<T> collection);
}

public class MoreConvenientList<T> : List<T>, IMoreConvenientListInterface<T> { }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.