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




स्पिन क्वांटम नंबर (14)

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


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

  • एक संरचना के साथ, डेटा भंडारण के लिए युक्त कक्षा के भीतर मेमोरी आवंटित की जाती है।
  • कक्षा के साथ, युक्त कक्षा में स्मृति के एक अलग क्षेत्र में नई कक्षा में एक सूचक शामिल होगा।

यह सरणी के साथ भी सच है, इसलिए structs की एक सरणी स्मृति में इस तरह दिखती है

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

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

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

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

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

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


इसे पूरा करने के लिए, 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

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


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

पीएस विशिष्ट मामले 'स्टैक्ट या संग्रह के साथ वर्ग' के लिए एक और बेंचमार्क है: https://.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;
            }
        }
    }
}

  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. एक संरचना में विनाशक नहीं हो सकता है। एक विनाशक वस्तु का एक ओवरराइड है। भेस में फाइनलाइज करें, और structs, मूल्य प्रकार होने के नाते, कचरा संग्रह के अधीन नहीं हैं।

    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 () के आभासी तरीकों को ओवरराइड कर सकती है।


स्ट्रूट्स और क्लासेस के बीच अंतर -

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

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

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

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

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

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


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

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

यदि आप सभी मतभेदों को समझाते हुए वीडियो के बाद हैं, तो आप भाग 2 9 - सी # ट्यूटोरियल देख सकते हैं - सी # में कक्षाओं और structs के बीच अंतर


.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.

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

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


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

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


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

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

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

स्ट्रक्चर ऑब्जेक्ट के विधि कॉल मान के बाद: 10 है

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

क्लास ऑब्जेक्ट के अंदर क्लास विधि के अंदर क्लास ऑब्जेक्ट का तरीका है: 20

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

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


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

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

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

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

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


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

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

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

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

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

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

  • मूल्य प्रकारों में हमेशा एक मान होता है
  • संदर्भ प्रकारों में शून्य- धारणा हो सकती है, जिसका अर्थ है कि वे इस समय किसी भी चीज़ का संदर्भ नहीं लेते हैं

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

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

जब आप चर या फ़ील्ड घोषित करते हैं, तो यहां दो प्रकार भिन्न होते हैं:

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

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

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

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

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

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

int? value = null;
value  = 1;




reference-type