संरचनाएं वंशानुक्रम का समर्थन क्यों नहीं करती हैं?


128

मुझे पता है कि .NET में संरचनाएं वंशानुक्रम का समर्थन नहीं करती हैं, लेकिन यह बिल्कुल स्पष्ट नहीं है कि वे इस तरह से सीमित क्यों हैं।

क्या तकनीकी कारण संरचना को अन्य संरचनाओं से विरासत में मिलने से रोकता है?


6
मैं इस कार्यक्षमता के लिए नहीं मर रहा हूं, लेकिन मैं कुछ मामलों के बारे में सोच सकता हूं जब संरचना वंशानुक्रम उपयोगी होगा: आप उत्तराधिकार के साथ एक पॉइंट 3 डी संरचना को प्वाइंट 2 डी संरचना को सीमित करना चाह सकते हैं, आप इसे मानने के लिए Int32 से विरासत में प्राप्त करना चाह सकते हैं। 1 और 100 के बीच, आप एक टाइप-डीईएफ बनाना चाहते हैं, जो कई फाइलों में दिखाई दे रहा है (टाइपिंग टाइप = टाइपबी ट्रिक में केवल फाइल स्कोप है), आदि
जूलियट

4
आप stackoverflow.com/questions/1082311/… को पढ़ना चाह सकते हैं , जो संरचनों के बारे में थोड़ा और बताते हैं और उन्हें एक निश्चित आकार तक ही सीमित क्यों रखा जाना चाहिए। यदि आप किसी संरचना में वंशानुक्रम का उपयोग करना चाहते हैं तो आपको संभवतः एक वर्ग का उपयोग करना चाहिए।
जस्टिन

1
और आप stackoverflow.com/questions/1222935/… को पढ़ना चाह सकते हैं क्योंकि यह गहराई में जाता है कि यह सिर्फ डॉटनेट प्लेटफॉर्म में क्यों नहीं किया जा सकता है। उन्होंने ठंड को सी ++ रास्ता बना दिया है, उन्हीं समस्याओं के साथ जो एक प्रबंधित मंच के लिए विनाशकारी हो सकते हैं।
डाइकैम

@ जस्टिन क्लासेस के पास प्रदर्शन लागत है जिससे संरचनाएं बच सकती हैं। और खेल विकास में जो वास्तव में मायने रखता है। तो कुछ मामलों में आपको एक वर्ग का उपयोग नहीं करना चाहिए यदि आप इसे मदद कर सकते हैं।
गेविन विलियम्स

@Dykam मुझे लगता है कि यह C # में किया जा सकता है। विनाशकारी एक अतिशयोक्ति है। मैं आज सी # में विनाशकारी कोड लिख सकता हूं जब मैं एक तकनीक से परिचित नहीं हूं। तो यह वास्तव में एक मुद्दा नहीं है। यदि संरचना वंशानुक्रम कुछ समस्याओं को हल कर सकता है और कुछ परिदृश्यों के तहत बेहतर प्रदर्शन दे सकता है, तो मैं इसके लिए हूं।
गेविन विलियम्स

जवाबों:


121

कारण मान प्रकार इनहेरिटेंस का समर्थन नहीं कर सकते क्योंकि एरे के कारण है।

समस्या यह है कि, प्रदर्शन और जीसी कारणों के लिए, मूल्य प्रकार के सरणियों को "इनलाइन" संग्रहीत किया जाता है। उदाहरण के लिए, दिया गया new FooType[10] {...}, यदि FooTypeकोई संदर्भ प्रकार है, तो प्रबंधित हीप पर 11 ऑब्जेक्ट बनाए जाएंगे (सरणी के लिए एक, और प्रत्येक प्रकार के उदाहरण के लिए 10)। यदि FooTypeइसके बजाय एक मूल्य प्रकार है, तो प्रबंधित हीप पर केवल एक उदाहरण बनाया जाएगा - सरणी के लिए (जैसा कि प्रत्येक सरणी मान को सरणी के साथ "इनलाइन" संग्रहीत किया जाएगा)।

अब, मान लीजिए कि हमारे पास मूल्य प्रकारों के साथ विरासत थी। जब सरणियों के उपरोक्त "इनलाइन स्टोरेज" व्यवहार के साथ संयुक्त, खराब चीजें होती हैं, जैसा कि सी ++ में देखा जा सकता है ।

इस छद्म सी # कोड पर विचार करें:

struct Base
{
    public int A;
}

struct Derived : Base
{
    public int B;
}

void Square(Base[] values)
{
  for (int i = 0; i < values.Length; ++i)
      values [i].A *= 2;
}

Derived[] v = new Derived[2];
Square (v);

सामान्य रूपांतरण नियमों के अनुसार, एक (बेहतर या बदतर के लिए) के लिए Derived[]परिवर्तनीय है Base[], इसलिए यदि आप उपरोक्त उदाहरण के लिए / संरचना / वर्ग / जी हैं, तो यह बिना किसी समस्या के, उम्मीद के अनुसार संकलन और चलाएगा। लेकिन अगर Baseऔर Derivedमूल्य प्रकार हैं, और सरणियों में स्टोर इनलाइन हैं, तो हमारे पास एक समस्या है।

हमारे पास एक समस्या है क्योंकि Square()इसके बारे में कुछ भी नहीं पता है Derived, यह सरणी के प्रत्येक तत्व तक पहुंचने के लिए केवल सूचक अंकगणितीय का उपयोग करेगा, एक स्थिर राशि ( sizeof(A)) द्वारा बढ़ाना । विधानसभा अस्पष्ट होगी:

for (int i = 0; i < values.Length; ++i)
{
    A* value = (A*) (((char*) values) + i * sizeof(A));
    value->A *= 2;
}

(हां, यह घिनौना असेंबली है, लेकिन मुद्दा यह है कि हम ज्ञात संकलन-समय स्थिरांक पर सरणी के माध्यम से वेतन वृद्धि करेंगे, बिना किसी ज्ञान के कि एक व्युत्पन्न प्रकार का उपयोग किया जा रहा है।)

इसलिए, यदि वास्तव में ऐसा हुआ है, तो हमारे पास भ्रष्टाचार के मुद्दों की स्मृति होगी। विशेष रूप से, के भीतर Square(), values[1].A*=2होगा वास्तव में बदलाव हो values[0].B!

डिबग करने की कोशिश करो कि !


11
उस समस्या का समझदार समाधान कास्ट फॉर्म [] का पता लगाने के लिए [] बाधित करना होगा। जैसे शॉर्ट [] से इंट [] पर कास्टिंग करना मना है, हालांकि शॉर्ट से इंट से कास्टिंग संभव है।
निकी

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

4
हां, लेकिन यह "समझदारी" है क्योंकि सरणी रूपांतरण निहित रूपांतरणों के लिए हैं, स्पष्ट रूपांतरणों के लिए नहीं। int के लिए शॉर्ट संभव है, लेकिन एक कास्ट की आवश्यकता होती है, इसलिए यह समझदार है कि शॉर्ट [] को int में नहीं बदला जा सकता है [] (रूपांतरण कोड की कमी, जैसे 'a.Select (x => (int) x) .ToArray () ) ')। यदि रनटाइम ने बेस से व्युत्पन्न तक कलाकारों को रोक दिया, तो यह "मस्सा" होगा, क्योंकि आईएस ने संदर्भ प्रकारों के लिए अनुमति दी थी। इसलिए हमारे पास दो अलग-अलग "मौसा" संभव हैं - संरचना की विरासत या सरणियों के बेस के रूपांतरणों के निषिद्ध रूपांतरणों के लिए।
16

3
कम से कम स्ट्रक्चर इनहेरिटेंस को रोककर हमारे पास एक अलग कीवर्ड है और अधिक आसानी से "स्ट्रक्चर्स विशेष हैं" कह सकते हैं, जैसा कि किसी चीज़ में "यादृच्छिक" सीमा होने के विपरीत है जो चीजों के एक सेट (कक्षाओं) के लिए काम करता है, लेकिन दूसरे (स्ट्रक्चर्स) के लिए नहीं । मुझे लगता है कि संरचना की सीमा को समझाना बहुत आसान है ("वे अलग हैं!")।
jonp

2
फ़ंक्शन का नाम 'स्क्वायर' से 'डबल' करने की आवश्यकता है
जॉन

69

कल्पना कीजिए कि आधारभूत संरचना विरासत में मिली है। फिर घोषणा:

BaseStruct a;
InheritedStruct b; //inherits from BaseStruct, added fields, etc.

a = b; //?? expand size during assignment?

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

इससे भी बेहतर, इस पर विचार करें:

BaseStruct[] baseArray = new BaseStruct[1000];

baseArray[500] = new InheritedStruct(); //?? morph/resize the array?

5
C ++ ने 'स्लाइसिंग' की अवधारणा की शुरुआत करते हुए इसका उत्तर दिया, ताकि यह एक समस्या है। तो, संरचना की विरासत का समर्थन क्यों नहीं किया जाना चाहिए?
jonp

1
अंतर्निहित संरचनाओं की सरणियों पर विचार करें, और याद रखें कि C # एक (स्मृति) प्रबंधित भाषा है। Slicing या किसी भी समान विकल्प CLR के मूल सिद्धांतों पर कहर बरपाएगा।
केनन ईके

4
@ जोंप: सॉल्व करने योग्य, हाँ। वांछित? यहां एक सोचा प्रयोग किया गया है: कल्पना करें कि क्या आपके पास एक बेस क्लास वेक्टर 2 डी (एक्स, वाई) और व्युत्पन्न क्लास वेक्टर 3 डी (एक्स, वाई, जेड) है। दोनों वर्गों में एक मैग्नीट्यूड गुण है जो क्रमशः sqrt (x ^ 2 + y ^ 2) और sqrt (x ^ 2 + y ^ 2 + z ^ 2) की गणना करता है। यदि आप 'वेक्टर 3 डी ए = वेक्टर 3 डी (5, 10, 15) लिखते हैं; Vector2D b = a? ’, D a.Magnitude == b.Magnitude’ क्या चाहिए? अगर हम 'a = (वेक्टर 3 डी) बी' लिखते हैं, तो क्या असाइनमेंट से पहले वैसा ही मान होना चाहिए? .NET डिजाइनरों ने शायद खुद से कहा, "नहीं, हमारे पास कोई नहीं होगा"।
जूलियट

1
सिर्फ इसलिए कि एक समस्या को हल किया जा सकता है, इसका मतलब यह नहीं है कि इसे हल किया जाना चाहिए। कभी-कभी यह उन परिस्थितियों से बचने के लिए सबसे अच्छा है जहां समस्या उत्पन्न होती है।
दान डिप्लो

@ kek444: स्ट्रक्चर Fooइनहेरिट करने के लिए Bara Fooको असाइन करने की अनुमति नहीं दी जानी चाहिए Bar, लेकिन एक ऐसे तरीके की घोषणा करने से कुछ उपयोगी प्रभाव पड़ सकते हैं: (1) Barपहले आइटम के रूप में विशेष रूप से नामित सदस्य बनाएं Fooऔर इसमें Fooशामिल करें सदस्य के नाम जो उन सदस्यों के लिए अन्य नाम हैं Bar, जो कोड का उपयोग Barकरने के लिए अनुकूलित किया गया था Foo, बिना किसी संदर्भ के thing.BarMemberसाथ सभी संदर्भों को बदलने के लिए thing.theBar.BarMember, और Barएक समूह के रूप में सभी क्षेत्रों को पढ़ने और लिखने की क्षमता बनाए रखने के लिए ; ...
सुपरकैट

14

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


8
उत्तराधिकार का लाभ लेने के लिए किसी को बहुरूपता का उपयोग करने की आवश्यकता नहीं है
rmeador

तो, आपके पास .NET में विरासत के कितने अलग-अलग प्रकार होंगे?
जॉन सॉन्डर्स

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

ऐसा इसलिए क्योंकि वे सभी System.Object से निकलते हैं। यह सिस्टम की बहुरूपता है। संरचना की तुलना में विशेष प्रकार।
जॉन सॉन्डर्स 16

बहुरूपता सामान्य प्रकार के मापदंडों के रूप में उपयोग की जाने वाली संरचनाओं के साथ सार्थक हो सकती है। बहुरूपता उन संरचनाओं के साथ काम करता है जो इंटरफेस को लागू करते हैं; इंटरफेस के साथ सबसे बड़ी समस्या यह है कि वे संरचनात्मक क्षेत्रों के लिए बायरेफ़्स को उजागर नहीं कर सकते हैं। अन्यथा, मुझे लगता है कि सबसे बड़ी बात यह है कि "विरासत में मिली" संरचनाएं जहाँ तक सहायक होंगी, वह एक प्रकार (संरचना या वर्ग) होगा Foo, जिसमें संरचना का एक क्षेत्र होता है, जो सदस्यों के स्वयं के रूप में Barसंबंध रखने में सक्षम होता है Bar, ताकि एक Point3dवर्ग उदा सकता है, Point2d xyलेकिन या Xतो उस क्षेत्र को संदर्भित कर सकता है । xy.XX
सुपरकैट

8

यहाँ डॉक्स का कहना है:

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

मूल रूप से, वे सरल डेटा रखने वाले हैं और इसलिए इनहेरिटेंस जैसी "अतिरिक्त सुविधाएँ" नहीं हैं। यह संभव है कि तकनीकी रूप से उनके लिए कुछ सीमित प्रकार की विरासतों का समर्थन करना संभव हो (न कि बहुरूपता, उनके कारण स्टैक पर होने के कारण), लेकिन मेरा मानना ​​है कि यह एक डिजाइन विकल्प भी है कि विरासत का समर्थन न करें (.NET में कई अन्य चीजों की तरह)। भाषाएँ हैं।)

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


4
यही कारण है कि विरासत नहीं है।
Dykam

मेरा मानना ​​है कि यहां जिस विरासत के बारे में बात की जा रही है, वह दो संरचनाओं का उपयोग करने में सक्षम नहीं है, जहां एक दूसरे के स्थान से विरासत में मिलती है, लेकिन एक संरचना को दूसरे से लागू करने और फिर से जोड़ने (यानी एक Point3Dसे निर्माण करने के लिए जोड़कर Point2D; आप सक्षम नहीं होंगे) के Point3Dबजाय का उपयोग करने के लिए Point2D, लेकिन आप Point3Dखरोंच से पूरी तरह से फिर से लागू करने के लिए नहीं होगा ।) कि कैसे मैं इसे वैसे भी व्याख्या की है ...
Blixt

संक्षेप में: यह बहुरूपता के बिना विरासत का समर्थन कर सकता है। यह नहीं है मेरा मानना ​​है कि उपयुक्त होने classपर किसी व्यक्ति को चुनने में मदद करने के लिए यह एक डिज़ाइन विकल्प है struct
ब्लिक्स

3

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

struct A {
    int property;
} // sizeof A == sizeof int

struct B : A {
    int childproperty;
} // sizeof B == sizeof int * 2

यदि यह संभव होगा, तो यह निम्नलिखित स्निपेट पर क्रैश होगा:

void DoSomething(A arg){};

...

B b;
DoSomething(b);

अंतरिक्ष को आकार ए के लिए आवंटित किया जाता है, आकार बी के लिए नहीं।


2
C ++ इस मामले को ठीक, IIRC को संभालता है। B का उदाहरण ए के आकार में फिट होने के लिए कटा हुआ है। यदि यह शुद्ध डेटा प्रकार है, जैसा कि .NET स्ट्रक्चर्स हैं, तो कुछ भी बुरा नहीं होगा। आप एक विधि के साथ थोड़ी सी समस्या में भाग लेते हैं जो कि A लौटता है और आप उस रिटर्न मान को B में संग्रहीत कर रहे हैं, लेकिन इसकी अनुमति नहीं होनी चाहिए। संक्षेप में, .NET डिज़ाइनर इससे निपट सकते थे यदि वे चाहते थे, लेकिन उन्होंने किसी कारण से नहीं किया।
rmeador

1
आपके DoSomething () के लिए, कोई समस्या नहीं होने की संभावना है (C ++ शब्दार्थ को मानते हुए) 'b' को 'A' क्रिएट करने के लिए "कटा हुआ" होगा। समस्या <i> सरणियों </ i> के साथ है। अपनी मौजूदा A और B संरचना और <c> DoSomething (A [] arg) {ar ​​[1] .property = 1;} </ c> विधि पर विचार करें। चूंकि मान प्रकार के सरणियाँ "इनलाइन" मानों को संग्रहीत करते हैं, DoSomething (वास्तविक = नया B [2] {}) वास्तविक [0] का कारण बनेगा। चिल्डप्रोपरेटी को सेट किया जाएगा, वास्तविक [1] .property। ये गलत है।
jonp

2
@ जॉन: मैं यह दावा नहीं कर रहा था, और मुझे नहीं लगता कि @jonp भी था। हम केवल इस बात का उल्लेख कर रहे थे कि यह समस्या पुरानी है और इसे हल कर दिया गया है, इसलिए .NET डिजाइनरों ने तकनीकी स्थायित्व के अलावा किसी अन्य कारण से इसका समर्थन नहीं करना चुना।
rmeador 15

यह ध्यान दिया जाना चाहिए कि "व्युत्पन्न प्रकार के एरे" समस्या सी + + के लिए नया नहीं है; देखें parashift.com/c+-faq-lite/proper-inheritance.html#faq-21.4 (C ++ में एरर्स बुराई हैं! ;-)
jonp

@ जॉन: व्युत्पन्न प्रकारों और आधार प्रकारों के "सरणियों का मिश्रण नहीं है" का समाधान हमेशा की तरह समस्या नहीं है। यही कारण है कि C ++ में सरणियाँ बुराई हैं (अधिक आसानी से स्मृति भ्रष्टाचार की अनुमति देता है), और क्यों .NET मान प्रकार के साथ विरासत का समर्थन नहीं करता है (संकलक और जेआईटी यह सुनिश्चित करते हैं कि ऐसा नहीं हो सकता)।
जोंप

3

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

यह कहते हुए कि, सेसिल हैज़ नेम ने इसे सही ढंग से दर्ज किया है।

मैं इस पर जोर देना चाहूंगा, मूल्य प्रकार स्टैक पर रह सकते हैं। इसका मतलब यह नहीं है कि वे हमेशा ऐसा करते हैं। स्थानीय चर, विधि मापदंडों सहित, होगा। अन्य सभी नहीं करेंगे। फिर भी, यह अभी भी कारण है कि उन्हें विरासत में नहीं मिला है। :-)


3

स्टैक पर संरचनाएं आवंटित की जाती हैं। इसका मतलब यह है कि मूल्य शब्दार्थ बहुत मुक्त हैं, और संरचना सदस्यों तक पहुंचना बहुत सस्ता है। यह बहुरूपता को नहीं रोकता है।

आपके पास प्रत्येक संरचनात्मक शुरुआत सूचक के साथ इसकी आभासी फ़ंक्शन तालिका हो सकती है। यह एक प्रदर्शन मुद्दा होगा (प्रत्येक संरचना कम से कम एक पॉइंटर के आकार की होगी), लेकिन यह उल्लेखनीय है। यह आभासी कार्यों की अनुमति देगा।

खेतों को जोड़ने के बारे में क्या?

ठीक है, जब आप स्टैक पर एक संरचना आवंटित करते हैं, तो आप एक निश्चित मात्रा में स्थान आवंटित करते हैं। आवश्यक स्थान को संकलन समय (चाहे समय से पहले या जब JITting) में निर्धारित किया जाता है। यदि आप फ़ील्ड जोड़ते हैं और फिर एक आधार प्रकार को असाइन करते हैं:

struct A
{
    public int Integer1;
}

struct B : A
{
    public int Integer2;
}

A a = new B();

यह स्टैक के कुछ अज्ञात भाग को अधिलेखित कर देगा।

विकल्प रनटाइम के लिए होता है ताकि किसी भी ए वेरिएबल के लिए केवल आकार (ए) बाइट्स लिखकर इसे रोका जा सके।

यदि B A में एक विधि को ओवरराइड करता है और उसके Integer2 क्षेत्र को संदर्भित करता है तो क्या होगा? या तो रनटाइम एक मेसअसेक्स्टैप्शन फेंकता है, या इसके बजाय विधि स्टैक पर कुछ यादृच्छिक डेटा तक पहुंचती है। इनमें से कोई भी अनुमन्य नहीं है।

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


1
लगभग। किसी और ने स्टैक के संदर्भ में स्लाइसिंग समस्या का उल्लेख नहीं किया, केवल सरणियों के संदर्भ में। और किसी और ने उपलब्ध समाधानों का उल्लेख नहीं किया।
user38001

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

@ user38001 "स्टैक पर संरचनाएं आवंटित की जाती हैं" - जब तक कि वे उदाहरण के क्षेत्र नहीं हैं, जिस स्थिति में उन्हें ढेर पर आवंटित किया जाता है।
डेविड क्लेम्फनर

2

यह एक बहुत लगातार सवाल की तरह लगता है। मुझे ऐसा लगता है कि मान जोड़ने के लिए "जहाँ आप वैरिएबल घोषित करते हैं वहाँ" टाइप किए जाते हैं; कार्यान्वयन विवरणों के अलावा, इसका मतलब है कि कोई ऑब्जेक्ट हेडर नहीं है जो ऑब्जेक्ट के बारे में कुछ कहता है, केवल चर जानता है कि किस तरह का डेटा वहां रहता है।


संकलक जानता है कि वहाँ क्या है। C ++ का संदर्भ देना यह उत्तर नहीं हो सकता है।
हेनक होल्टरमैन 15

आपने C ++ कहाँ से प्राप्त किया? मैं इन-प्लेस कहने के साथ जाऊंगा क्योंकि यही व्यवहार से सबसे अच्छा मेल खाता है, स्टैक एक कार्यान्वयन विवरण है, जो MSDN ब्लॉग लेख को उद्धृत करता है।
सेसिल का 19

हां, C ++ का उल्लेख करना बुरा था, बस मेरे विचार की ट्रेन। लेकिन सवाल से हटकर अगर रनटाइम की जानकारी की जरूरत है, तो स्ट्रक्चर्स के पास 'ऑब्जेक्ट हेडर' क्यों नहीं होना चाहिए? संकलक उन्हें वैसे भी मैश कर सकता है जो उसे पसंद है। यह एक [स्ट्रक्चरलेआउट] संरचना पर एक हेडर भी छिपा सकता है।
हेंक होल्टरमैन

क्योंकि संरचना मूल्य प्रकार हैं, यह ऑब्जेक्ट हेडर के साथ आवश्यक नहीं है क्योंकि रन-टाइम हमेशा सामग्री को अन्य मूल्य प्रकारों (एक बाधा) के रूप में कॉपी करता है। यह हेडर के साथ कोई मतलब नहीं होगा, क्योंकि यही संदर्भ-प्रकार की कक्षाएं हैं: P
सेसिल का नाम

1

संरचनाएं समर्थन इंटरफेस करती हैं, इसलिए आप इस तरह से कुछ बहुरूपी चीजें कर सकते हैं।


0

IL एक स्टैक-आधारित भाषा है, इसलिए किसी तर्क के साथ एक विधि को कॉल करना कुछ इस तरह से होता है:

  1. स्टैक पर तर्क पुश करें
  2. विधि को बुलाओ।

जब विधि चलती है, तो वह अपने तर्क को प्राप्त करने के लिए स्टैक से कुछ बाइट्स निकालती है। यह बिल्कुल पता है कितने बाइट को पॉप करने के लिए क्योंकि तर्क या तो एक संदर्भ प्रकार सूचक है (32-बिट पर हमेशा 4 बाइट्स) या यह एक मूल्य प्रकार है जिसके लिए आकार हमेशा सटीक रूप से जाना जाता है।

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

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


1
C ++ ने हल किया है कि, असली समस्या के लिए इस उत्तर को पढ़ें: stackoverflow.com/questions/1222935/…
Dykam
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.