दिलचस्प पोस्ट
इनपुट प्रकार = "सबमिट करें" बनाम बटन टैग वे विनिमेय हैं? असाइनमेंट ऑपरेटर को ले जाएं और `यदि (यह! = & Rhs)` इस चित्र में आयतों को कैसे पहचाना जाए? एक बटन क्लिक किए जाने पर jQuery का उपयोग करते हुए एक ऑडियो फ़ाइल चलाएं मैं एक आईएसओ 8601 दिन-समय की स्ट्रिंग को पायथन डीट टाइम ऑब्जेक्ट में कैसे अनुवाद कर सकता हूं? Django – परिपत्र मॉडल आयात मुद्दा अक्षांश और देशांतर से पूरा पता कैसे प्राप्त करें? MySQL, उपयोगकर्ताओं को रैंक प्राप्त करें ऐड डीबग में है, तो क्यों Gradle रिलीज़ मोड में मेरे मॉड्यूल का निर्माण करता है क्या मुझे HTML में मेरे आईएमजी के लिए ऊंचाई और चौड़ाई विशेषताओं को निर्दिष्ट करना चाहिए? प्रतिक्रिया देने वाली प्रतिक्रियाएं अनचाहे प्रकार प्रकार: त्रुटि: सुपर अभिव्यक्ति या तो रिक्त या फ़ंक्शन होती है, अनिर्धारित नहीं कैसे "ठीक" जावास्क्रिप्ट में एक कस्टम ऑब्जेक्ट बनाएँ? मैं JTableHeader के एक JTable में नियंत्रण कैसे रख सकता हूं? क्यों नहीं ICloneable <टी>? C ++ कंस्ट्रक्टर नाम के बाद एक बृहदान्त्र क्या करता है?

क्यों / जब आप नेट में नेस्टेड कक्षाओं का उपयोग करना चाहिए? या आपको नहीं करना चाहिए?

कैथलीन डैर्ड के हालिया ब्लॉग पोस्ट में , वह एनएटी में नेस्टेड क्लासेस का उपयोग करने के लिए एक दिलचस्प कारण प्रस्तुत करता है। हालांकि, उन्होंने यह भी उल्लेख किया है कि FxCop नेस्टेड कक्षाओं को पसंद नहीं करता है। मैं मानता हूं कि लोग FxCop के नियम लिख रहे हैं बेवकूफ नहीं हैं, इसलिए उस स्थिति के पीछे तर्क होना चाहिए, लेकिन मैं इसे ढूंढने में सक्षम नहीं हूं।

वेब के समाधान से एकत्रित समाधान "क्यों / जब आप नेट में नेस्टेड कक्षाओं का उपयोग करना चाहिए? या आपको नहीं करना चाहिए?"

नेस्टेड क्लास का उपयोग करें जब आप घोंसले के शिकार वर्ग केवल संलग्न कक्षा के लिए उपयोगी होते हैं। उदाहरण के लिए, नेस्टेड क्लासेस आपको कुछ (सरल) लिखने की अनुमति देते हैं:

public class SortedMap { private class TreeNode { TreeNode left; TreeNode right; } } 

आप एक ही स्थान पर अपनी कक्षा की पूरी परिभाषा कर सकते हैं, आपको किसी भी पीआईएमपीएल हुप्स के माध्यम से कूदने की जरूरत नहीं है, ताकि यह तय हो सके कि आपका वर्ग कैसे काम करता है, और बाहरी दुनिया को आपके क्रियान्वयन के कुछ भी देखने की जरूरत नहीं है।

यदि ट्रीएनोड क्लास बाहरी था, तो आपको या तो सभी क्षेत्रों को public या इसका उपयोग करने के लिए get/set तरीकों का एक गुच्छा बनाना होगा। बाहर की दुनिया में एक अन्य वर्ग उनके intellisense प्रदूषण होगा

सन के जावा ट्यूटोरियल से:

नेस्टेड क्लासेस का उपयोग क्यों करें? नेस्टेड कक्षाओं का उपयोग करने के लिए कई आकर्षक कारण हैं, उनमें से:

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

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

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

उच्च-स्तरीय कक्षाओं के भीतर और अधिक पठनीय, रख-रखावयोग्य कोड-घोंसले के छोटे वर्ग, उस कोड के करीब स्थित हैं जहां इसका उपयोग किया जाता है।

पूरी तरह से आलसी और धागा सुरक्षित एकलटन पैटर्न

 public sealed class Singleton { Singleton() { } public static Singleton Instance { get { return Nested.instance; } } class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly Singleton instance = new Singleton(); } } 

स्रोत: http://www.yoda.arachsys.com/csharp/singleton.html

यह उपयोग पर निर्भर करता है मैं शायद ही कभी एक पब्लिक नेस्टेड क्लास का उपयोग करूँगा लेकिन निजी नेस्टेड क्लासेस को सभी समय का उपयोग करना होगा एक उपकृत वस्तु के लिए एक निजी नेस्टेड क्लास का उपयोग किया जा सकता है जिसका इरादा केवल माता-पिता के अंदर ही किया जा सकता है इसका एक उदाहरण तब होगा जब एक हाशलेट क्लास में निजी एंट्री ऑब्जेक्ट को केवल आंतरिक रूप से स्टोर करने के लिए शामिल किया जाता है

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

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

ऊपर सूचीबद्ध अन्य कारणों के अलावा, एक और कारण है कि मैं नेस्टेड कक्षाओं का उपयोग करने के लिए न केवल सोच सकता हूँ बल्कि वास्तव में सार्वजनिक नेस्टेड क्लासेस। जो एक से अधिक सामान्य वर्गों के साथ काम करते हैं, जो समान सामान्य प्रकार पैरामीटर्स साझा करते हैं, एक सामान्य नामस्थान घोषित करने की क्षमता अत्यंत उपयोगी होगी। दुर्भाग्य से, नेट (या कम से कम सी #) सामान्य नामस्थानों के विचार का समर्थन नहीं करता है। तो एक ही लक्ष्य को पूरा करने के लिए, हम एक ही लक्ष्य को पूरा करने के लिए सामान्य कक्षाओं का उपयोग कर सकते हैं। तार्किक इकाई से संबंधित निम्नलिखित उदाहरण वर्गों को लें:

 public class BaseDataObject < tDataObject, tDataObjectList, tBusiness, tDataAccess > where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new() where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess> { } public class BaseDataObjectList < tDataObject, tDataObjectList, tBusiness, tDataAccess > : CollectionBase<tDataObject> where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new() where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess> { } public interface IBaseBusiness < tDataObject, tDataObjectList, tBusiness, tDataAccess > where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new() where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess> { } public interface IBaseDataAccess < tDataObject, tDataObjectList, tBusiness, tDataAccess > where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new() where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess> where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess> { } 

हम एक सामान्य नामस्थान (नेस्टेड कक्षाओं के द्वारा लागू) का उपयोग करके इन वर्गों के हस्ताक्षर को सरल बना सकते हैं:

 public partial class Entity < tDataObject, tDataObjectList, tBusiness, tDataAccess > where tDataObject : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObject where tDataObjectList : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObjectList, new() where tBusiness : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseBusiness where tDataAccess : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseDataAccess { public class BaseDataObject {} public class BaseDataObjectList : CollectionBase<tDataObject> {} public interface IBaseBusiness {} public interface IBaseDataAccess {} } 

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

उदाहरण के लिए:

Entity.cs

 public partial class Entity < tDataObject, tDataObjectList, tBusiness, tDataAccess > where tDataObject : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObject where tDataObjectList : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObjectList, new() where tBusiness : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseBusiness where tDataAccess : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseDataAccess { } 

Entity.BaseDataObject.cs

 partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess> { public class BaseDataObject { public DataTimeOffset CreatedDateTime { get; set; } public Guid CreatedById { get; set; } public Guid Id { get; set; } public DataTimeOffset LastUpdateDateTime { get; set; } public Guid LastUpdatedById { get; set; } public static implicit operator tDataObjectList(DataObject dataObject) { var returnList = new tDataObjectList(); returnList.Add((tDataObject) this); return returnList; } } } 

Entity.BaseDataObjectList.cs

 partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess> { public class BaseDataObjectList : CollectionBase<tDataObject> { public tDataObjectList ShallowClone() { var returnList = new tDataObjectList(); returnList.AddRange(this); return returnList; } } } 

Entity.IBaseBusiness.cs

 partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess> { public interface IBaseBusiness { tDataObjectList Load(); void Delete(); void Save(tDataObjectList data); } } 

Entity.IBaseDataAccess.cs

 partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess> { public interface IBaseDataAccess { tDataObjectList Load(); void Delete(); void Save(tDataObjectList data); } } 

दृश्य स्टूडियो समाधान एक्सप्लोरर की फाइलें तब आयोजित की जाती हैं जैसे:

 Entity.cs + Entity.BaseDataObject.cs + Entity.BaseDataObjectList.cs + Entity.IBaseBusiness.cs + Entity.IBaseDataAccess.cs 

और आप सामान्य नामस्थान को निम्न की तरह कार्यान्वित करेंगे:

User.cs

 public partial class User : Entity < User.DataObject, User.DataObjectList, User.IBusiness, User.IDataAccess > { } 

User.DataObject.cs

 partial class User { public class DataObject : BaseDataObject { public string UserName { get; set; } public byte[] PasswordHash { get; set; } public bool AccountIsEnabled { get; set; } } } 

User.DataObjectList.cs

 partial class User { public class DataObjectList : BaseDataObjectList {} } 

User.IBusiness.cs

 partial class User { public interface IBusiness : IBaseBusiness {} } 

User.IDataAccess.cs

 partial class User { public interface IDataAccess : IBaseDataAccess {} } 

और फ़ाइलों को समाधान एक्सप्लोरर में व्यवस्थित किया जाएगा:

 User.cs + User.DataObject.cs + User.DataObjectList.cs + User.IBusiness.cs + User.IDataAccess.cs 

उपरोक्त एक सामान्य नाम स्थान के रूप में बाहरी कक्षा का उपयोग करने का एक सरल उदाहरण है। मैंने "सामान्य नामस्थान" बना दिया है जिसमें 9 या अधिक प्रकार के पैरामीटर शामिल हैं I उन प्रकार के पैरामीटर को रखने के लिए उन सभी 9 प्रकारों में सिंक्रनाइज़ किए गए हैं जिन्हें टाइप पैरामीटर जानना जरूरी है, खासकर जब कोई नया पैरामीटर जोड़ने पर। सामान्य नामस्थानों का उपयोग उस कोड को अधिक प्रबंधनीय और पठनीय बनाता है।

नेस्टेड कक्षाओं के लिए अभी तक उल्लेख नहीं किया गया एक अन्य उपयोग सामान्य प्रकारों के अलगाव है। उदाहरण के लिए, मान लीजिए एक को स्थिर कक्षाओं के कुछ जेनेरिक परिवारों के पास रखना है, जो कुछ मापदंडों के मानों के साथ-साथ कई मापदंडों के साथ तरीकों को ले सकते हैं, और कम पैरामीटर वाले प्रतिनिधियों को उत्पन्न कर सकते हैं। उदाहरण के लिए, एक एक स्थिर विधि रखना चाहती है जो एक String<string, int> Action<string, int, double> और एक String<string, int> जो कि आपूर्ति की गई कार्रवाई को 3.5 से double पारित करते हुए कॉल करेगी; एक भी एक स्थिर तरीका हो सकता है जो एक Action<string, int, double> और एक Action<string> उत्पन्न कर सकता है, 7 को int रूप में पारित कर सकता है और 5.3 को double रूप में जेनेरिक नेस्टेड क्लासेस का प्रयोग करके, कोई भी विधि इनवॉशन्स की तरह बन सकता है:

 MakeDelegate<string,int>.WithParams<double>(theDelegate, 3.5); MakeDelegate<string>.WithParams<int,double>(theDelegate, 7, 5.3); 

या, क्योंकि प्रत्येक अभिव्यक्ति में उत्तरार्द्ध प्रकार अनुमान लगाए जा सकते हैं, हालांकि पूर्व वाले नहीं कर सकते हैं:

 MakeDelegate<string,int>.WithParams(theDelegate, 3.5); MakeDelegate<string>.WithParams(theDelegate, 7, 5.3); 

नेस्टेड जेनेरिक प्रकारों का उपयोग करना यह बताने के लिए संभव है कि कौन सा प्रतिनिधियों समग्र प्रकार के वर्णन के कुछ हिस्सों पर लागू हैं।

निम्नलिखित आवश्यकताओं के लिए नेस्टेड क्लासेस का उपयोग किया जा सकता है:

  1. डेटा का वर्गीकरण
  2. जब मुख्य वर्ग का तर्क जटिल होता है और आप महसूस करते हैं कि आपको कक्षा प्रबंधन करने के लिए अधीनस्थ वस्तुओं की आवश्यकता होती है
  3. जब आप ऐसा करते हैं कि कक्षा का राज्य और अस्तित्व पूरी तरह से संलग्न वर्ग पर निर्भर करता है

मैं अक्सर नेस्टेड कक्षाओं का उपयोग कार्यान्वयन को छिपाने के लिए करता हूं। एरिक लिपर्ट के उत्तर से यहां एक उदाहरण:

 abstract public class BankAccount { private BankAccount() { } // Now no one else can extend BankAccount because a derived class // must be able to call a constructor, but all the constructors are // private! private sealed class ChequingAccount : BankAccount { ... } public static BankAccount MakeChequingAccount() { return new ChequingAccount(); } private sealed class SavingsAccount : BankAccount { ... } } 

यह पैटर्न जेनेरिक के उपयोग के साथ भी बेहतर हो जाता है दो अच्छे उदाहरणों के लिए यह प्रश्न देखें। इसलिए मैं लिखना समाप्त करता हूँ

 Equality<Person>.CreateComparer(p => p.Id); 

के बजाय

 new EqualityComparer<Person, int>(p => p.Id); 

साथ ही मेरे पास Equality<Person> की एक सामान्य सूची हो सकती है, लेकिन EqualityComparer<Person, int> नहीं EqualityComparer<Person, int>

 var l = new List<Equality<Person>> { Equality<Person>.CreateComparer(p => p.Id), Equality<Person>.CreateComparer(p => p.Name) } 

जहाँ तक

 var l = new List<EqualityComparer<Person, ??>>> { new EqualityComparer<Person, int>>(p => p.Id), new EqualityComparer<Person, string>>(p => p.Name) } 

संभव नहीं है। माता-पिता वर्ग से नेस्टेड क्लास के उत्तराधिकारी का फायदा यही है

एक और मामला (एक ही प्रकृति का – छिपाना कार्यान्वयन) जब आप केवल एक वर्ग के लिए क्लास के सदस्य (फ़ील्ड, प्रॉपर्टी आदि) सुलभ बनाना चाहते हैं:

 public class Outer { class Inner //private class { public int Field; //public field } static inner = new Inner { Field = -1 }; // Field is accessible here, but in no other class } 

जैसा कि सार फैक्ट्री पैटर्न के कार्यान्वयन का उल्लेख नहीं किया गया है, उस कोड को क्लास क्लस्टर पैटर्न हासिल करने के लिए विस्तारित किया जा सकता है जो सार फैक्ट्री पैटर्न पर आधारित है।

मैं नेस्ट अपवादों को पसंद करता हूं जो एक ही वर्ग के लिए अद्वितीय हैं I जो कि किसी भी अन्य स्थान से कभी नहीं फेंके जाते हैं

उदाहरण के लिए:

 public class MyClass { void DoStuff() { if (!someArbitraryCondition) { // This is the only class from which OhNoException is thrown throw new OhNoException( "Oh no! Some arbitrary condition was not satisfied!"); } // Do other stuff } public class OhNoException : Exception { // Constructors calling base() } } 

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

ध्यान रखें कि आपको नेस्टेड क्लास का परीक्षण करने की आवश्यकता होगी। अगर यह निजी है, तो आप इसे अलगाव में नहीं परीक्षण कर पाएंगे।

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

तो, आप केवल कम जटिलता से जुड़े निजी नेस्टेड कक्षाओं को लागू कर सकते हैं।