ओपी द्वारा संदर्भित स्रोत में कुछ विश्वसनीयता है ... लेकिन Microsoft के बारे में क्या है - संरचना उपयोग पर रुख क्या है? मैंने Microsoft से कुछ अतिरिक्त सीखने की कोशिश की , और यहाँ मैंने पाया:
एक वर्ग के बजाय एक संरचना को परिभाषित करने पर विचार करें यदि प्रकार के उदाहरण छोटे और आमतौर पर अल्पकालिक हैं या आमतौर पर अन्य वस्तुओं में एम्बेडेड हैं।
किसी संरचना को तब तक परिभाषित न करें जब तक कि सभी प्रकार में निम्नलिखित विशेषताएं न हों:
- यह तार्किक रूप से आदिम प्रकारों (पूर्णांक, डबल, और इसी तरह) के समान एकल मूल्य का प्रतिनिधित्व करता है।
- इसका एक उदाहरण आकार 16 बाइट्स से छोटा है।
- यह अपरिवर्तनीय है।
- इसे बार-बार बॉक्सिंग नहीं करना पड़ेगा।
Microsoft लगातार उन नियमों का उल्लंघन करता है
ठीक है, # 2 और # 3 वैसे भी। हमारे प्रिय शब्दकोश में 2 आंतरिक संरचनाएं हैं:
[StructLayout(LayoutKind.Sequential)] // default for structs
private struct Entry //<Tkey, TValue>
{
// View code at *Reference Source
}
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Enumerator :
IEnumerator<KeyValuePair<TKey, TValue>>, IDisposable,
IDictionaryEnumerator, IEnumerator
{
// View code at *Reference Source
}
* संदर्भ स्रोत
'JonnyCantCode.com' स्रोत को 4 में से 3 मिले - # 4 के बाद से काफी क्षमा करने योग्य शायद एक मुद्दा नहीं होगा। यदि आप अपने आप को एक संरचना बॉक्सिंग पाते हैं, तो अपनी वास्तुकला पर पुनर्विचार करें।
आइए देखें कि Microsoft इन संरचनाओं का उपयोग क्यों करेगा:
- प्रत्येक संरचना,
Entry
औरEnumerator
, एकल मूल्यों का प्रतिनिधित्व करते हैं।
- गति
Entry
डिक्शनरी क्लास के बाहर कभी भी एक पैरामीटर के रूप में पारित नहीं किया जाता है। आगे की जांच से पता चलता है कि IEnumerable के कार्यान्वयन को संतुष्ट करने के लिए, डिक्शनरी उस Enumerator
संरचना का उपयोग करती है, जो हर बार एक एन्यूमरेटर का अनुरोध करने पर ... समझ में आता है।
- शब्दकोश वर्ग के लिए आंतरिक।
Enumerator
सार्वजनिक है क्योंकि डिक्शनरी एन्युमरेबल है और IEnumerator इंटरफ़ेस कार्यान्वयन के लिए समान पहुँच होनी चाहिए - जैसे IEnumerator गेटर।
अद्यतन - इसके अलावा, महसूस करें कि जब कोई संरचना इंटरफ़ेस लागू करती है - जैसा कि एन्यूमरेटर करता है - और उस कार्यान्वित प्रकार के लिए डाला जाता है, तो संरचना एक संदर्भ प्रकार बन जाती है और ढेर में चली जाती है। आंतरिक शब्दकोश वर्ग के लिए, गणनाकार है अभी भी एक मान प्रकार। हालाँकि, जैसे ही कोई विधि कॉल करती है GetEnumerator()
, एक संदर्भ-प्रकार IEnumerator
वापस आ जाता है।
जो कुछ हम यहां नहीं देखते हैं, वह केवल 16 बाइट्स या इंस्टेंस आकार को बनाए रखने के लिए किसी भी प्रयास या सबूत का है।
- ऊपर की संरचना में कुछ भी घोषित नहीं किया गया है
readonly
- अपरिवर्तनीय नहीं
- इन संरचना का आकार 16 बाइट्स से अधिक हो सकता है
Entry
एक अनिर्धारित जीवन है (से Add()
, करने के लिए Remove()
, Clear()
या कचरा संग्रहण);
और ... 4. दोनों संरचनाएं TKey और TValue को संग्रहीत करती हैं, जो हम सभी जानते हैं कि संदर्भ प्रकार होने में काफी सक्षम हैं (अतिरिक्त बोनस जानकारी)
हशेड कीज़ के बावजूद, शब्दकोश भाग में तेज़ होते हैं क्योंकि एक संरचना को भेजना एक संदर्भ प्रकार की तुलना में तेज़ होता है। यहां, मेरे पास Dictionary<int, int>
300,000 यादृच्छिक पूर्णांकों को क्रमिक रूप से बढ़ी हुई कुंजियों के साथ संग्रहीत किया गया है।
क्षमता: 312874
याद: 2660827 बाइट्स
पूर्ण आकार: 5ms
भरने के लिए कुल समय: 889 मिलियन
क्षमता : आंतरिक सरणी से पहले उपलब्ध तत्वों की संख्या का आकार परिवर्तन होना चाहिए।
MemSize : एक मेमोरीस्ट्रीम में शब्दकोश क्रमबद्ध करने और एक बाइट लंबाई (हमारे उद्देश्यों के लिए पर्याप्त सटीक) प्राप्त करने से निर्धारित होता है।
पूर्ण आकार : 150862 तत्वों से 312874 तत्वों तक आंतरिक सरणी का आकार बदलने में लगने वाला समय। जब आप जानते हैं कि प्रत्येक तत्व क्रमिक रूप से कॉपी किया गया है Array.CopyTo()
, तो वह बहुत जर्जर नहीं है।
भरने के लिए कुल समय : लॉगिंग और OnResize
स्रोत पर जोड़े गए एक घटना के कारण, मोटे तौर पर तिरछा ; हालांकि, ऑपरेशन के दौरान 15 बार आकार बदलते हुए 300k पूर्णांक भरने के लिए अभी भी प्रभावशाली है। जिज्ञासा से बाहर, भरने के लिए कुल समय क्या होगा यदि मैं पहले से ही क्षमता जानता था? 13ms
तो, अब, अगर Entry
एक वर्ग थे? क्या ये समय या मैट्रिक्स वास्तव में इतना भिन्न होगा?
क्षमता: 312874
याद: 2660827 बाइट्स
पूर्ण आकार: 26ms
भरने के लिए कुल समय: 964 मिलियन
जाहिर है, बड़ा अंतर आकार बदलने में है। कोई फर्क अगर शब्दकोश क्षमता के साथ आरंभ किया जाता है? पर्याप्त नहीं होने के साथ संबंधित ... 12ms ।
क्या होता है, क्योंकि Entry
एक संरचना है, इसे संदर्भ प्रकार की तरह आरंभीकरण की आवश्यकता नहीं है। यह मूल्य प्रकार की सुंदरता और प्रतिबंध दोनों है। Entry
संदर्भ प्रकार के रूप में उपयोग करने के लिए , मुझे निम्नलिखित कोड डालना होगा:
/*
* Added to satisfy initialization of entry elements --
* this is where the extra time is spent resizing the Entry array
* **/
for (int i = 0 ; i < prime ; i++)
{
destinationArray[i] = new Entry( );
}
/* *********************************************** */
कारण यह है कि मुझे Entry
संदर्भ प्रकार के रूप में प्रत्येक सरणी तत्व को एमएसडीएन में पाया जा सकता है : संरचना डिजाइन । संक्षेप में:
एक संरचना के लिए एक डिफ़ॉल्ट निर्माता प्रदान न करें।
यदि कोई संरचना डिफॉल्ट कंस्ट्रक्टर को परिभाषित करती है, जब संरचना की सरणियाँ बनाई जाती हैं, तो सामान्य भाषा रनटाइम प्रत्येक ऐरे एलिमेंट पर डिफ़ॉल्ट कंस्ट्रक्टर को स्वचालित रूप से निष्पादित करता है।
कुछ कंपाइलर, जैसे कि C # कंपाइलर, डिफॉल्ट कंस्ट्रक्टर वाले स्ट्रक्चर को अनुमति नहीं देते हैं।
यह वास्तव में काफी सरल है और हम असिमोव के रोबोटिक्स के थ्री लॉज़ से उधार लेंगे :
- उपयोग करने के लिए संरचना सुरक्षित होनी चाहिए
- जब तक यह नियम # 1 का उल्लंघन नहीं करेगा, तब तक संरचना को अपना कार्य कुशलतापूर्वक करना चाहिए
- जब तक इसके नियम # 1 को पूरा करने के लिए इसके विनाश की आवश्यकता नहीं है, तब तक इसके उपयोग के दौरान संरचना बरकरार रहनी चाहिए
... हम इस से क्या लेते हैं : संक्षेप में, मूल्य प्रकारों के उपयोग के साथ जिम्मेदार हैं। वे त्वरित और कुशल हैं, लेकिन कई अप्रत्याशित व्यवहारों को पैदा करने की क्षमता रखते हैं अगर ठीक से रखरखाव नहीं किया जाता है (यानी अनजाने में प्रतियां)।
System.Drawing.Rectangle
इन तीनों नियमों का उल्लंघन करता है।