.NET में संरचना और वर्ग के बीच अंतर क्या है?


जवाबों:


1058

.NET में, दो प्रकार के प्रकार, संदर्भ प्रकार और मूल्य प्रकार हैं

संरचना मूल्य प्रकार हैं और कक्षाएं संदर्भ प्रकार हैं

सामान्य अंतर यह है कि एक संदर्भ प्रकार ढेर पर रहता है, और एक मूल्य प्रकार इनलाइन रहता है, अर्थात, जहां भी यह आपका चर या क्षेत्र परिभाषित होता है।

एक मान प्रकार वाले चर में संपूर्ण मान प्रकार होता है । एक संरचना के लिए, इसका मतलब है कि चर में संपूर्ण संरचना शामिल है, जिसके सभी क्षेत्र हैं।

एक संदर्भ प्रकार वाले चर में एक पॉइंटर, या स्मृति में कहीं और संदर्भ होता है जहां वास्तविक मूल्य रहता है।

यह एक लाभ है, के साथ शुरू करने के लिए:

  • मूल्य प्रकारों में हमेशा एक मान होता है
  • संदर्भ प्रकार एक हो सकते हैं अशक्त -reference, जिसका अर्थ है कि वे इस समय सब पर कुछ भी का उल्लेख नहीं है

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

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

जब आप चर या क्षेत्र घोषित करते हैं, तो यहां बताया गया है कि दो प्रकार कैसे भिन्न होते हैं:

  • चर: मान प्रकार स्टैक पर रहता है, संदर्भ प्रकार ढेर पर पॉइंटर के रूप में रहता है जहाँ ढेर मेमोरी होती है जहाँ वास्तविक मेमोरी रहती है (हालांकि एरिक लिपिपर्ट्स लेख श्रृंखला ध्यान दें : स्टैक इम्प्लीमेंटेशन डिटेल है ।)
  • वर्ग / संरचना-क्षेत्र: मान प्रकार पूरी तरह से अंदर रहता है, संदर्भ प्रकार प्रकार के अंदर एक संकेत के रूप में रहता है, कहीं कहीं ढेर स्मृति में जहां वास्तविक स्मृति रहती है।

43
पूर्णता के हित में, मुझे यह उल्लेख करना चाहिए कि एरिक लिपर्ट ने कहा है कि स्टैक एक कार्यान्वयन विवरण है , जब भी मैं ऊपर स्टैक का उल्लेख करता हूं, तो एरिक की पोस्ट (ओं) को ध्यान में रखें।
लसे वी। कार्लसन

2
क्या यह सब C ++ के लिए भी मान्य है?
कोरे तुगे

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

4
@KorayTugay नहीं यह नहीं है।
जूमइन

9
C ++ संरचना और वर्ग में @KorayTugay एक चीज को छोड़कर बिल्कुल समान हैं - डिफ़ॉल्ट एक्सेस प्रतिबंध (कक्षा में डिफ़ॉल्ट रूप से निजी है, संरचना सार्वजनिक है)
berkus

207

प्रत्येक का एक संक्षिप्त सारांश:

केवल कक्षाएं:

  • वंशानुक्रम का समर्थन कर सकते हैं
  • संदर्भ (पॉइंटर) प्रकार हैं
  • संदर्भ शून्य हो सकता है
  • नए उदाहरण प्रति मेमोरी ओवरहेड रखें

केवल संरचनाएं:

  • वंशानुक्रम का समर्थन नहीं कर सकता
  • मूल्य प्रकार हैं
  • मूल्य द्वारा पास किए गए हैं (जैसे पूर्णांक)
  • एक अशक्त संदर्भ नहीं हो सकता है (जब तक कि अशक्त का उपयोग नहीं किया जाता है)
  • नए उदाहरण प्रति मेमोरी ओवरहेड न करें - जब तक कि 'बॉक्सिंग' न हो

दोनों वर्ग और संरचनाएं:

  • क्या यौगिक डेटा प्रकार आमतौर पर कुछ वैरिएबल होते हैं जिनका कुछ तार्किक संबंध होता है
  • विधियाँ और घटनाएँ शामिल कर सकते हैं
  • इंटरफेस का समर्थन कर सकते हैं

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

1
संरचना अन्य चरणों / वर्गों से वंशानुक्रम का समर्थन नहीं करती है, लेकिन आप एक संरचना पर एक इंटरफ़ेस लागू कर सकते हैं।
thewpfguy

2
आप स्पष्ट कर सकते हैं कि जब आप दावा करते हैं कि आप क्या चाहते हैं, तो यह दावा किया जाता है कि "नए उदाहरण के अनुसार मेमोरी ओवरहेड न हो" । मेरी पहली व्याख्या यह थी कि आप दावा कर रहे थे - स्पष्ट रूप से बेतुका - कि संरचनाएं शून्य मेमोरी का उपयोग करती हैं। तब मुझे लगा कि शायद आप यह कहना चाह रहे हैं कि एक संरचना, एक वर्ग के विपरीत, इसके सदस्य क्षेत्रों के योग के रूप में बिल्कुल स्मृति की आवश्यकता होती है, और अधिक नहीं। लेकिन तब मैंने Googled के लिए c# struct memory overheadऔर हंस पसंत के इस जवाब को पाया जो कहता है कि नहीं, यह मामला नहीं है। तो क्या करते हैं आप क्या मतलब है?
मार्क अमेरी

4
@MarkAmery मेरी वही प्रारंभिक प्रतिक्रिया थी जो आपको "नो मेमोरी ओवरहेड" अभिव्यक्ति के लिए आईडी के रूप में थी, लेकिन मुझे लगता है कि ओपी इस तथ्य का उल्लेख कर रहा है कि उदाहरणों classको प्रबंधित मेमोरी (कचरा कलेक्टर द्वारा नियंत्रित) किया जाता है, जबकि उदाहरण structनहीं हैं ।
हच

1
"संरचना मूल्य द्वारा (जैसे पूर्णांक) पास की गई है" झूठी है: सभी चर मान से पारित किए जाते हैं, संदर्भ प्रकार भी। यदि आप संदर्भ द्वारा एक चर पास करना चाहते हैं तो आपको "रेफरी" कीवर्ड का उपयोग करना होगा। jonskeet.uk/csharp/parameters.html#ref
मार्को स्टैफ़ोली

41

.NET में, संदर्भ प्रकारों और मूल्य प्रकारों के बीच संरचना और वर्ग की घोषणाएं भिन्न होती हैं।

जब आप किसी संदर्भ प्रकार को पास करते हैं तो वास्तव में केवल एक संग्रहीत होता है। सभी कोड जो एक्सेस को एक्सेस करते हैं, वही एक्सेस कर रहा है।

जब आप राउंड पास एक वैल्यू टाइप करते हैं तो हर एक कॉपी है। सभी कोड अपनी कॉपी पर काम कर रहे हैं।

इसे एक उदाहरण के साथ दिखाया जा सकता है:

struct MyStruct 
{
    string MyProperty { get; set; }
}

void ChangeMyStruct(MyStruct input) 
{ 
   input.MyProperty = "new value";
}

...

// Create value type
MyStruct testStruct = new MyStruct { MyProperty = "initial value" }; 

ChangeMyStruct(testStruct);

// Value of testStruct.MyProperty is still "initial value"
// - the method changed a new copy of the structure.

एक वर्ग के लिए यह अलग होगा

class MyClass 
{
    string MyProperty { get; set; }
}

void ChangeMyClass(MyClass input) 
{ 
   input.MyProperty = "new value";
}

...

// Create reference type
MyClass testClass = new MyClass { MyProperty = "initial value" };

ChangeMyClass(testClass);

// Value of testClass.MyProperty is now "new value" 
// - the method changed the instance passed.

कक्षाएं कुछ भी नहीं हो सकती हैं - संदर्भ एक अशक्त को इंगित कर सकता है।

संरचनाएं वास्तविक मूल्य हैं - वे खाली हो सकती हैं लेकिन कभी भी शून्य नहीं होती हैं। इस कारण से, संरचना में हमेशा एक डिफ़ॉल्ट निर्माता होता है जिसमें कोई पैरामीटर नहीं होता है - उन्हें एक 'शुरुआती मूल्य' की आवश्यकता होती है।


@ T.Todua हाँ, ऊपर बेहतर उत्तर हैं, कि मैंने वोट दिया और इस एक को प्रदान करने के बाद उत्तर के रूप में चुना - यह एसओ के शुरुआती बीटा से है जब हम अभी भी नियमों का पता लगा रहे थे।
कीथ

1
मुझे नहीं पता कि आपने मुझे सही तरीके से समझा है, मैंने वास्तव में आपके उत्तर को स्वीकार / स्वीकार कर लिया है (जैसा कि उपरोक्त उत्तरों के विपरीत है), क्योंकि आपके अच्छे उदाहरण थे (केवल सैद्धांतिक व्याख्या नहीं, जैसा कि उपरोक्त उत्तर के विपरीत है, जिसमें बिना उदाहरण के केवल सैद्धांतिक स्पष्टीकरण था। )।
टोडुआ

24

संरचनाओं और वर्गों के बीच अंतर:

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

21

Microsoft की कक्षा और संरचना के बीच चयन से ...

अंगूठे के एक नियम के रूप में, एक ढांचे में अधिकांश प्रकार की कक्षाएं होनी चाहिए। हालाँकि, कुछ परिस्थितियाँ हैं, जिनमें मूल्य प्रकार की विशेषताएँ, संरचना का उपयोग करना अधिक उचित बनाती हैं।

एक वर्ग के बजाय एक संरचना पर विचार करें :

  • यदि प्रकार के उदाहरण छोटे होते हैं और आमतौर पर अल्पकालिक होते हैं या आमतौर पर अन्य वस्तुओं में एम्बेडेड होते हैं।

एक्स एक struct से बचें जब तक प्रकार है सभी निम्नलिखित विशेषताएं की:

  • यह तार्किक रूप से आदिम प्रकार (इंट, डबल, आदि) के समान एकल मूल्य का प्रतिनिधित्व करता है।
  • यह 16 बाइट्स के तहत एक उदाहरण आकार है।
  • यह अपरिवर्तनीय है। (बदला नहीं जा सकता)
  • इसे बार-बार बॉक्सिंग नहीं करना पड़ेगा।

19

अन्य उत्तरों में वर्णित सभी अंतरों के अलावा:

  1. Structs एक स्पष्ट parameterless निर्माता नहीं हो सकता है , जबकि एक वर्ग कर सकते हैं
  2. संरचना में विध्वंसक नहीं हो सकते , जबकि एक वर्ग कर सकता है
  3. संरचनाएं किसी अन्य संरचना या वर्ग से विरासत में नहीं मिल सकती हैं जबकि एक वर्ग दूसरे वर्ग से विरासत में मिल सकता है। (दोनों इंटरफ़ेस से कक्षाएं और कार्यान्वयन कर सकते हैं।)

यदि आप सभी अंतरों को समझाने वाले वीडियो के बाद हैं, तो आप भाग 29 - C # ट्यूटोरियल की जांच कर सकते हैं - C # में कक्षाओं और संरचनाओं के बीच अंतर


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

15

कक्षाओं के उदाहरण प्रबंधित हीप पर संग्रहीत किए जाते हैं। सभी चर 'एक उदाहरण' युक्त केवल ढेर पर उदाहरण के लिए एक संदर्भ है। किसी विधि में किसी वस्तु को पास करने से संदर्भ की एक प्रति पारित हो जाती है, वस्तु ही नहीं।

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

अंतर को C ++ / CLI नामों से बेहतर बनाया गया है: "रेफ क्लास" एक वर्ग है जैसा कि पहले वर्णित है, "मूल्य वर्ग" एक वर्ग है जिसे दूसरे के रूप में वर्णित किया गया है। सी # द्वारा उपयोग किए जाने वाले कीवर्ड "क्लास" और "स्ट्रक्चर" बस कुछ ऐसी चीजें हैं जिन्हें सीखना चाहिए।


11
+------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|                        |                                                Struct                                                |                                               Class                                               |
+------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
| Type                   | Value-type                                                                                           | Reference-type                                                                                    |
| Where                  | On stack / Inline in containing type                                                                 | On Heap                                                                                           |
| Deallocation           | Stack unwinds / containing type gets deallocated                                                     | Garbage Collected                                                                                 |
| Arrays                 | Inline, elements are the actual instances of the value type                                          | Out of line, elements are just references to instances of the reference type residing on the heap |
| Aldel Cost             | Cheap allocation-deallocation                                                                        | Expensive allocation-deallocation                                                                 |
| Memory usage           | Boxed when cast to a reference type or one of the interfaces they implement,                         | No boxing-unboxing                                                                                |
|                        | Unboxed when cast back to value type                                                                 |                                                                                                   |
|                        | (Negative impact because boxes are objects that are allocated on the heap and are garbage-collected) |                                                                                                   |
| Assignments            | Copy entire data                                                                                     | Copy the reference                                                                                |
| Change to an instance  | Does not affect any of its copies                                                                    | Affect all references pointing to the instance                                                    |
| Mutability             | Should be immutable                                                                                  | Mutable                                                                                           |
| Population             | In some situations                                                                                   | Majority of types in a framework should be classes                                                |
| Lifetime               | Short-lived                                                                                          | Long-lived                                                                                        |
| Destructor             | Cannot have                                                                                          | Can have                                                                                          |
| Inheritance            | Only from an interface                                                                               | Full support                                                                                      |
| Polymorphism           | No                                                                                                   | Yes                                                                                               |
| Sealed                 | Yes                                                                                                  | When have sealed keyword                                                                          |
| Constructor            | Can not have explicit parameterless constructors                                                     | Any constructor                                                                                   |
| Null-assignments       | When marked with nullable question mark                                                              | Yes (+ When marked with nullable question mark in C# 8+)                                          |
| Abstract               | No                                                                                                   | When have abstract keyword                                                                        |
| Member Access Modifiers| public, private, internal                                                                            | public, protected, internal, protected internal, private protected                                |
+------------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+

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

1
@ensisNoctis उन गलतियों के लिए क्षमा करें और संपादन के लिए धन्यवाद। मुझे अपने उत्तरों को
😅

8

संरचना बनाम कक्षा

एक संरचना एक मूल्य प्रकार है इसलिए इसे स्टैक पर संग्रहीत किया जाता है, लेकिन एक वर्ग एक संदर्भ प्रकार है और ढेर पर संग्रहीत किया जाता है।

एक संरचना विरासत और बहुरूपता का समर्थन नहीं करती है, लेकिन एक वर्ग दोनों का समर्थन करता है।

डिफ़ॉल्ट रूप से, सभी संरचना सदस्य सार्वजनिक होते हैं लेकिन कक्षा सदस्य डिफ़ॉल्ट रूप से प्रकृति में होते हैं।

जैसा कि एक संरचना एक मूल्य प्रकार है, हम एक संरचनात्मक वस्तु को अशक्त नहीं कर सकते हैं, लेकिन यह एक वर्ग के लिए मामला नहीं है।


5
"सभी संरचनात्मक सदस्य सार्वजनिक हैं" के बारे में: यदि मुझसे गलती नहीं हुई है, तो यह गलत है। "नेस्टेड क्लासेस और स्ट्रक्चर्स सहित क्लास मेंबर्स और स्ट्रक्चर मेंबर्स के लिए एक्सेस लेवल डिफॉल्ट रूप से प्राइवेट होता है।" msdn.microsoft.com/en-us/library/ms173121.aspx
नैट कुक

8

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

  • एक संरचना के साथ, सरणी में संरचना का उदाहरण होता है
  • एक वर्ग के साथ, सरणी में स्मृति में कहीं और कक्षा के उदाहरण के लिए एक सूचक होता है

तो स्मृति में इस तरह की एक संरचना दिखती है

[struct][struct][struct][struct][struct][struct][struct][struct]

जबकि वर्गों की एक सरणी इस तरह दिखती है

[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]

कक्षाओं की एक सरणी के साथ, जिन मूल्यों में आप रुचि रखते हैं, वे सरणी में संग्रहीत नहीं हैं, लेकिन स्मृति में कहीं और हैं।

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

आधुनिक सीपीयू जितनी धीमी गति से काम करता है, वह संख्या में कमी नहीं करता है, यह मेमोरी से डेटा प्राप्त कर रहा है, और एक L1 कैश हिट रैम से डेटा पढ़ने की तुलना में कई गुना तेज है।

यहां कुछ कोड दिए गए हैं, जिनका आप परीक्षण कर सकते हैं। मेरी मशीन पर, क्लास एरे के माध्यम से पुनरावृत्ति करना, स्ट्रक्चर ऐरे की तुलना में ~ 3x अधिक समय लेता है।

    private struct PerformanceStruct
    {
        public int i1;
        public int i2;
    }

    private class PerformanceClass
    {
        public int i1;
        public int i2;
    }

    private static void DoTest()
    {
        var structArray = new PerformanceStruct[100000000];
        var classArray = new PerformanceClass[structArray.Length];

        for (var i = 0; i < structArray.Length; i++)
        {
            structArray[i] = new PerformanceStruct();
            classArray[i] = new PerformanceClass();
        }

        long total = 0;
        var sw = new Stopwatch();
        sw.Start();
        for (var loops = 0; loops < 100; loops++)
        for (var i = 0; i < structArray.Length; i++)
        {
            total += structArray[i].i1 + structArray[i].i2;
        }

        sw.Stop();
        Console.WriteLine($"Struct Time: {sw.ElapsedMilliseconds}");
        sw = new Stopwatch();
        sw.Start();
        for (var loops = 0; loops < 100; loops++)
        for (var i = 0; i < classArray.Length; i++)
        {
            total += classArray[i].i1 + classArray[i].i2;
        }

        Console.WriteLine($"Class Time: {sw.ElapsedMilliseconds}");
    }

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

@MarkAmery मैं थोड़ा स्पष्ट करने की कोशिश की है। जिस बिंदु पर मैं वास्तव में प्रयास कर रहा था, वह था कि मूल्य और संदर्भ प्रकारों के साथ काम करने वाले तरीकों में अंतर और प्रदर्शन पर इसका प्रभाव पड़ता है। मैं फिर से समझाने की कोशिश नहीं कर रहा था कि मूल्य और संदर्भ प्रकार क्या हैं क्योंकि यह बहुत सारे अन्य उत्तरों में किया जाता है।
विल काल्डरवुड

7

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

आओ हम कहते हैं कि हमारे पास एक वर्ग और एक संरचना है:

class A{
  public int a, b;
}
struct B{
  public int a, b;
}

और मुख्य विधि में, हमारे पास 4 ऑब्जेक्ट हैं।

static void Main{
  A c1 = new A(), c2 = new A();
  c1.a = c1.b = c2.a = c2.b = 1;
  B s1 = new B(), s2 = new B();
  s1.a = s1.b = s2.a = s2.b = 1;
}

फिर:

s1.Equals(s2) // true
s1.Equals(c1) // false
c1.Equals(c2) // false
c1 == c2 // false

तो , अंक-जैसी वस्तुओं के लिए संरचनाएं अनुकूल हैं, जैसे अंक (x और y निर्देशांक सहेजें)। और कक्षाएं दूसरों के लिए अनुकूल हैं। भले ही 2 लोगों का नाम, ऊंचाई, वजन ... हो, फिर भी वे 2 लोग हैं।


6

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

अन्य लोग शायद आपको आई से अधिक विस्तार दे सकते हैं, लेकिन मैं उस संरचना का उपयोग करता हूं जब मैं जिस संरचना के लिए जा रहा हूं वह सरल है।


4

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

structs:

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

वर्ग:

  • संदर्भ प्रकार मान
  • ढेर में संग्रहीत
  • एक गतिशील रूप से आवंटित वस्तु के लिए एक संदर्भ स्टोर करें
  • कंस्ट्रक्टरों को नए ऑपरेटर के साथ आमंत्रित किया जाता है, लेकिन यह ढेर पर मेमोरी आवंटित नहीं करता है
  • एकाधिक चर में एक ही वस्तु का संदर्भ हो सकता है
  • दूसरे चर द्वारा संदर्भित वस्तु को प्रभावित करने के लिए एक चर पर संचालन संभव है

कोड नमूना

    static void Main(string[] args)
    {
        //Struct
        myStruct objStruct = new myStruct();
        objStruct.x = 10;
        Console.WriteLine("Initial value of Struct Object is: " + objStruct.x);
        Console.WriteLine();
        methodStruct(objStruct);
        Console.WriteLine();
        Console.WriteLine("After Method call value of Struct Object is: " + objStruct.x);
        Console.WriteLine();

        //Class
        myClass objClass = new myClass(10);
        Console.WriteLine("Initial value of Class Object is: " + objClass.x);
        Console.WriteLine();
        methodClass(objClass);
        Console.WriteLine();
        Console.WriteLine("After Method call value of Class Object is: " + objClass.x);
        Console.Read();
    }
    static void methodStruct(myStruct newStruct)
    {
        newStruct.x = 20;
        Console.WriteLine("Inside Struct Method");
        Console.WriteLine("Inside Method value of Struct Object is: " + newStruct.x);
    }
    static void methodClass(myClass newClass)
    {
        newClass.x = 20;
        Console.WriteLine("Inside Class Method");
        Console.WriteLine("Inside Method value of Class Object is: " + newClass.x);
    }
    public struct myStruct
    {
        public int x;
        public myStruct(int xCons)
        {
            this.x = xCons;
        }
    }
    public class myClass
    {
        public int x;
        public myClass(int xCons)
        {
            this.x = xCons;
        }
    }

उत्पादन

संरचना वस्तु का प्रारंभिक मूल्य है: 10

इनसाइड स्ट्रक्चर मेथड इनसाइड मेथड ऑफ स्ट्रक्चर ऑब्जेक्ट का मान है: २०

मेथड के बाद स्ट्रक्चर ऑब्जेक्ट का कॉल वैल्यू है: १०

कक्षा वस्तु का प्रारंभिक मूल्य है: 10

इनसाइड क्लास मेथड इनसाइड मेथड ऑफ क्लास ऑब्जेक्ट है: 20

विधि के बाद क्लास ऑब्जेक्ट का मूल्य है: 20

यहां आप मूल्य द्वारा कॉल और संदर्भ द्वारा कॉल के बीच अंतर स्पष्ट रूप से देख सकते हैं।


4
  1. एक कक्षा में घोषित घटनाओं में उनका + = और - = पहुंच स्वचालित रूप से लॉक के माध्यम से लॉक हो जाता है (यह) उन्हें थ्रेड को सुरक्षित बनाने के लिए (स्थिर घटनाओं को टाइपोफ़ क्लास पर लॉक किया जाता है)। एक संरचना में घोषित घटनाओं में उनका + = और - = का उपयोग स्वचालित रूप से लॉक नहीं होता है। एक संरचना के लिए एक लॉक (यह) काम नहीं करेगा क्योंकि आप केवल संदर्भ प्रकार की अभिव्यक्ति पर लॉक कर सकते हैं।

  2. संरचना उदाहरण बनाने से कचरा संग्रह नहीं हो सकता (जब तक कि निर्माणकर्ता प्रत्यक्ष या अप्रत्यक्ष रूप से एक संदर्भ प्रकार का उदाहरण नहीं बनाता है) जबकि संदर्भ प्रकार का उदाहरण बनाने से कचरा संग्रह हो सकता है।

  3. एक संरचना में हमेशा एक अंतर्निहित सार्वजनिक डिफ़ॉल्ट निर्माता होता है।

    class DefaultConstructor
    {
        static void Eg()
        {
            Direct     yes = new   Direct(); // Always compiles OK
            InDirect maybe = new InDirect(); // Compiles if constructor exists and is accessible
            //...
        }
    }

    इसका मतलब यह है कि एक संरचना हमेशा तात्कालिक होती है जबकि एक वर्ग ऐसा नहीं हो सकता है क्योंकि उसके सभी निर्माता निजी हो सकते हैं।

    class NonInstantiable
    {
        private NonInstantiable() // OK
        {
        }
    }
    
    struct Direct
    {
        private Direct() // Compile-time error
        {
        }
    }
  4. एक संरचना में एक विध्वंसक नहीं हो सकता। एक विध्वंसक वस्तु का सिर्फ एक ओवरराइड है। भेष बदलकर, और संरचना, मूल्य प्रकार होने के नाते, कचरा संग्रह के अधीन नहीं हैं।

    struct Direct
    {
        ~Direct() {} // Compile-time error
    }
    class InDirect
    {
        ~InDirect() {} // Compiles OK
    }
    
    And the CIL for ~Indirect() looks like this:
    
    .method family hidebysig virtual instance void
            Finalize() cil managed
    {
      // ...
    } // end of method Indirect::Finalize
  5. एक संरचना स्पष्ट रूप से सील है, एक वर्ग नहीं है।
    एक संरचना अमूर्त नहीं हो सकती, एक वर्ग कर सकता है।
    एक संरचना इसके निर्माता में आधार () को कॉल नहीं कर सकती है जबकि एक वर्ग जिसमें कोई स्पष्ट आधार वर्ग नहीं है।
    एक संरचना दूसरे वर्ग का विस्तार नहीं कर सकती है, एक वर्ग कर सकता है।
    एक संरचित संरक्षित सदस्यों की घोषणा नहीं कर सकता (उदाहरण के लिए, फ़ील्ड, नेस्टेड प्रकार) एक वर्ग कर सकता है।
    एक संरचना सार फ़ंक्शन सदस्यों की घोषणा नहीं कर सकती, एक सार वर्ग कर सकता है।
    एक संरचना वर्चुअल फ़ंक्शन सदस्यों की घोषणा नहीं कर सकती है, एक वर्ग कर सकता है।
    एक संरचना सील समारोह सदस्यों की घोषणा नहीं कर सकती है, एक वर्ग कर सकता है।
    एक संरचना ओवरराइड फ़ंक्शन सदस्यों की घोषणा नहीं कर सकती है, एक वर्ग कर सकता है।
    इस नियम के लिए एक अपवाद यह है कि एक सिस्टम System.Object, अर्थात, () और GetHashCode (), और ToString () के वर्चुअल तरीकों को ओवरराइड कर सकता है।


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

@supercat हाँ, एक संरचना में एक गैर-स्थैतिक घटना बहुत अजीब होगी, और यह केवल उत्परिवर्तित संरचनाओं के लिए उपयोगी होगी, और घटना स्वयं (यदि यह "फ़ील्ड-जैसी" घटना है) तो संरचना को "परिवर्तनशील" में बदल देती है "श्रेणी और संरचना में संदर्भ प्रकार का एक क्षेत्र भी पेश करता है। संरचनाओं में गैर-स्थैतिक घटनाओं को बुराई होना चाहिए।
जेपी स्टिग नीलसन

@JeppeStigNielsen: एकमात्र पैटर्न जो मैं देख सकता था कि किसी संरचना के लिए एक घटना के होने का क्या अर्थ होगा यदि संरचना का उद्देश्य एक वर्ग वस्तु के लिए एक अपरिवर्तनीय संदर्भ रखना है जिसके लिए यह एक प्रॉक्सी के रूप में व्यवहार करता है। ऑटो-ईवेंट ऐसे परिदृश्य में पूरी तरह से बेकार होगा, हालांकि; इसके बजाय, सदस्यता लेने और सदस्यता समाप्त करने की घटनाओं को संरचना के पीछे वर्ग में स्थानांतरित करना होगा। मैं चाहता हूं कि .NET के पास (या इसे परिभाषित करना संभव है) एक 'कैश-बॉक्स "संरचना का प्रकार जिसमें प्रारंभिक रूप से अशक्त छिपा हुआ क्षेत्र है Object, जो संरचना के एक बॉक्स की प्रतिलिपि का संदर्भ
रखेगा

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

4

जैसा कि पहले उल्लेख किया गया है: कक्षाएं संदर्भ प्रकार हैं जबकि संरचना सभी परिणामों के साथ मूल्य प्रकार हैं।

नियम फ्रेमवर्क डिज़ाइन के अंगूठे के रूप में, कक्षाओं के बजाय स्ट्रक्चर्स का उपयोग करने की अनुशंसा करता है यदि:

  • यह 16 बाइट्स के तहत एक उदाहरण आकार है
  • यह तार्किक रूप से आदिम प्रकार (इंट, डबल, आदि) के समान एकल मूल्य का प्रतिनिधित्व करता है
  • यह अपरिवर्तनीय है
  • इसे बार-बार बॉक्सिंग नहीं करना पड़ेगा

3

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

पुनश्च विशिष्ट मामले के लिए एक और बेंचमार्क 'संग्रह या संग्रह के साथ वर्ग' है: https://stackoverflow.com/a/45276657/506147

BenchmarkDotNet=v0.10.10, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233540 Hz, Resolution=309.2586 ns, Timer=TSC
.NET Core SDK=2.0.3
  [Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
  Clr    : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2115.0
  Core   : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT


            Method |  Job | Runtime |     Mean |     Error |    StdDev |      Min |      Max |   Median | Rank |  Gen 0 | Allocated |
------------------ |----- |-------- |---------:|----------:|----------:|---------:|---------:|---------:|-----:|-------:|----------:|
  TestStructReturn |  Clr |     Clr | 17.57 ns | 0.1960 ns | 0.1834 ns | 17.25 ns | 17.89 ns | 17.55 ns |    4 | 0.0127 |      40 B |
   TestClassReturn |  Clr |     Clr | 21.93 ns | 0.4554 ns | 0.5244 ns | 21.17 ns | 23.26 ns | 21.86 ns |    5 | 0.0229 |      72 B |
 TestStructReturn8 |  Clr |     Clr | 38.99 ns | 0.8302 ns | 1.4097 ns | 37.36 ns | 42.35 ns | 38.50 ns |    8 | 0.0127 |      40 B |
  TestClassReturn8 |  Clr |     Clr | 23.69 ns | 0.5373 ns | 0.6987 ns | 22.70 ns | 25.24 ns | 23.37 ns |    6 | 0.0305 |      96 B |
  TestStructReturn | Core |    Core | 12.28 ns | 0.1882 ns | 0.1760 ns | 11.92 ns | 12.57 ns | 12.30 ns |    1 | 0.0127 |      40 B |
   TestClassReturn | Core |    Core | 15.33 ns | 0.4343 ns | 0.4063 ns | 14.83 ns | 16.44 ns | 15.31 ns |    2 | 0.0229 |      72 B |
 TestStructReturn8 | Core |    Core | 34.11 ns | 0.7089 ns | 1.4954 ns | 31.52 ns | 36.81 ns | 34.03 ns |    7 | 0.0127 |      40 B |
  TestClassReturn8 | Core |    Core | 17.04 ns | 0.2299 ns | 0.2150 ns | 16.68 ns | 17.41 ns | 16.98 ns |    3 | 0.0305 |      96 B |

कोड परीक्षण:

using System;
using System.Text;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Columns;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using DashboardCode.Routines.Json;

namespace Benchmark
{
    //[Config(typeof(MyManualConfig))]
    [RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
    [ClrJob, CoreJob]
    [HtmlExporter, MarkdownExporter]
    [MemoryDiagnoser]
    public class BenchmarkStructOrClass
    {
        static TestStruct testStruct = new TestStruct();
        static TestClass testClass = new TestClass();
        static TestStruct8 testStruct8 = new TestStruct8();
        static TestClass8 testClass8 = new TestClass8();
        [Benchmark]
        public void TestStructReturn()
        {
            testStruct.TestMethod();
        }

        [Benchmark]
        public void TestClassReturn()
        {
            testClass.TestMethod();
        }


        [Benchmark]
        public void TestStructReturn8()
        {
            testStruct8.TestMethod();
        }

        [Benchmark]
        public void TestClassReturn8()
        {
            testClass8.TestMethod();
        }

        public class TestStruct
        {
            public int Number = 5;
            public struct StructType<T>
            {
                public T Instance;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance;
            }

            private StructType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private StructType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private StructType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private StructType<int> Method4(int i)
            {
                var x = new StructType<int>();
                x.List = new List<string>();
                x.Instance = ++i;
                return x;
            }
        }

        public class TestClass
        {
            public int Number = 5;
            public class ClassType<T>
            {
                public T Instance;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance;
            }

            private ClassType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private ClassType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private ClassType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private ClassType<int> Method4(int i)
            {
                var x = new ClassType<int>();
                x.List = new List<string>();
                x.Instance = ++i;
                return x;
            }
        }

        public class TestStruct8
        {
            public int Number = 5;
            public struct StructType<T>
            {
                public T Instance1;
                public T Instance2;
                public T Instance3;
                public T Instance4;
                public T Instance5;
                public T Instance6;
                public T Instance7;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance1;
            }

            private StructType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private StructType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private StructType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private StructType<int> Method4(int i)
            {
                var x = new StructType<int>();
                x.List = new List<string>();
                x.Instance1 = ++i;
                return x;
            }
        }

        public class TestClass8
        {
            public int Number = 5;
            public class ClassType<T>
            {
                public T Instance1;
                public T Instance2;
                public T Instance3;
                public T Instance4;
                public T Instance5;
                public T Instance6;
                public T Instance7;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance1;
            }

            private ClassType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private ClassType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private ClassType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private ClassType<int> Method4(int i)
            {
                var x = new ClassType<int>();
                x.List = new List<string>();
                x.Instance1 = ++i;
                return x;
            }
        }
    }
}

2

संरचनाएं वास्तविक मूल्य हैं - वे खाली हो सकती हैं लेकिन कभी भी शून्य नहीं होती हैं

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

int? value = null;
value  = 1;

1
विदित हो कि यह केवल संश्लिष्ट शर्करा है जो 'अशक्त <int> मान = अशक्त;' पढ़ता है।
एरिक वैन ब्रैकेल

@ ErikvanBrakel यह सिंटैक्टिक चीनी नहीं है। अलग-अलग मुक्केबाजी नियमों का मतलब है (object)(default(int?)) == nullजो आप किसी भी अन्य प्रकार के मूल्य के साथ नहीं कर सकते हैं, क्योंकि यहां केवल चीनी की तुलना में अधिक है। केवल चीनी है int?के लिए Nullable<int>
जॉन हन्ना

-1; यह इस सवाल का समाधान नहीं करता है कि संरचना और कक्षाओं के बीच अंतर क्या है, और इस तरह, यह उस उत्तर पर एक टिप्पणी होनी चाहिए जिसका आप उत्तर दे रहे हैं, एक अलग उत्तर नहीं। (हालांकि शायद अगस्त 2008 में साइट के मानक अलग थे!)
मार्क अमेरी

1

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

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

एक आदिम प्रकार के एक चर या क्षेत्र की नकल दूसरे को कॉपी करेगा। संरचना के एक चर या क्षेत्र को दूसरे में कॉपी करना पूर्व उदाहरण के सभी क्षेत्रों (सार्वजनिक और निजी) को बाद के उदाहरण में कॉपी करेगा। एक चर या संदर्भ प्रकार के क्षेत्र को दूसरे में कॉपी करने से उत्तरार्द्ध पूर्व (यदि कोई हो) के समान उदाहरण को संदर्भित करेगा।

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

.NET में, किसी भी उपरोक्त शब्दार्थ को लागू करने के लिए मूल्य प्रकारों के लिए संभव है, बशर्ते कि उनके सभी क्षेत्र इसी तरह कर सकते हैं। एक संदर्भ प्रकार, हालांकि, केवल परस्पर संदर्भ शब्दार्थ या अपरिवर्तनीय शब्दार्थ को लागू कर सकता है; परिवर्तनशील संदर्भ प्रकारों के क्षेत्रों के साथ मूल्य प्रकार या तो परस्पर संदर्भ शब्दार्थ या अजीब संकर शब्दार्थ को लागू करने तक सीमित हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.