2008-11-07 6 views
52

अगर मैं सी # में एक struct इस तरह स्वत: गुणों का उपयोग करके निर्धारित किए हैं:कॉल करना आवश्यक क्यों है: यह() सी # में स्वचालित गुणों का उपयोग करने के लिए एक संरचना पर?

public struct Address 
{ 
    public Address(string line1, string line2, string city, string state, string zip) 
    { 
     Line1 = line1; 
     Line2 = line2; 
     City = city; 
     State = state; 
     Zip = zip; 
    } 

    public string Line1 { get; protected set; } 
    public string Line2 { get; protected set; } 
    public string City { get; protected set; } 
    public string State { get; protected set; } 
    public string Zip { get; protected set; } 
} 

जब मैं फ़ाइल का निर्माण करने का प्रयास, मैं The 'this' object cannot be used before all of its fields are assigned to कह एक संकलन त्रुटि मिलती है।

public Address(string line1, string line2, string city, string state, string zip): this() 
{ 
    Line1 = line1; 
    Line2 = line2; 
    City = city; 
    State = state; 
    Zip = zip; 
} 

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

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

+0

एक 'संरक्षित' सदस्य को 'संरचना' में अनुमति नहीं दी जानी चाहिए, जैसे कि इसे 'मुहरबंद वर्ग' में अनुमति नहीं है। –

उत्तर

52

नोट: सी # 6 के रूप में, यह आवश्यक नहीं है - लेकिन आप केवल पढ़ने के साथ सी # 6 वैसे भी स्वचालित रूप से लागू गुण का उपयोग करना चाहिए ...

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

यह कष्टप्रद है, लेकिन यह वही तरीका है। क्या आप वाकई वास्तव में यह एक संरचना बनना चाहते हैं? और एक संरक्षक पर संरक्षित सेटटर का उपयोग क्यों करें (जिसे से नहीं लिया जा सकता है)?

+0

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

+7

अपरिवर्तनीय! = संरचना। यह मेरे लिए बहुत संरचना-वाई महसूस नहीं करता है। यह एक * बुरा * पसंद नहीं है, लेकिन यह एक ऐसा नहीं है जिसे मैं बनाना चाहता हूं। मैं अपरिवर्तनीयता को स्पष्ट कर दूंगा हालांकि: "सामान्य" (केवल पढ़ने योग्य) संपत्ति और एक पठनीय क्षेत्र का उपयोग करें। यह एक शर्म की बात है कि स्वचालित गुणों में "रीडोनली" सेटर्स (cont) –

+5

नहीं हो सकता है ... जो केवल रचनात्मक क्षेत्रों में ही पहुंच योग्य होगा, जैसा कि एक पाठक क्षेत्र को असाइन करना है। कंपाइलर दृश्यों के पीछे केवल पढ़ने के लिए फ़ील्ड उत्पन्न कर सकता है, और सेटर पहुंच को फ़ील्ड एक्सेस में सीधे रूपांतरित कर सकता है। –

0

एक संपत्ति Get विधि और/या Set विधि के encapsulation से अधिक कुछ नहीं है। सीएलआर में मेटाडेटा है जो इंगित करता है कि विशेष तरीकों को गुणों के रूप में माना जाना चाहिए, जिसका अर्थ है कि कंपाइलर्स को कुछ संरचनाओं की अनुमति देनी चाहिए जो इसे विधियों के साथ अनुमति नहीं देनी चाहिए। उदाहरण के लिए, यदि XFoo की एक पठन-लेखन संपत्ति है, तो एक कंपाइलर Foo.X += 5 को Foo.SET_X_METHOD(Foo.GET_X_METHOD() + 5) में अनुवाद करेगा (हालांकि विधियों को अलग-अलग नाम दिया गया है, और आम तौर पर नाम से पहुंच योग्य नहीं हैं)।

हालांकि एक ऑटोप्रोपर्टी संपत्ति के बाहर किसी भी कोड के दृष्टिकोण से, एक क्षेत्र की तरह कम या कम व्यवहार करने के लिए इस तरह से एक निजी क्षेत्र तक पहुंचने के लिए एक जोड़ी को लागू करता है, एक ऑटोप्रोपर्टी एक ऑटोप्रोपर्टी है किसी अन्य संपत्ति की तरह प्राप्त/सेट विधियों की जोड़ी। नतीजतन, Foo.X = 5; जैसे एक बयान का अनुवाद Foo.SET_X_METHOD(5) है। चूंकि सी # कंपाइलर बस एक विधि कॉल के रूप में देखता है, और चूंकि विधियों में कोई मेटाडेटा शामिल नहीं है, यह इंगित करने के लिए कि वे कौन से फ़ील्ड पढ़ते हैं या लिखते हैं, संकलक विधि कॉल को तब तक रोक देगा जब तक कि यह Foo के प्रत्येक फ़ील्ड को नहीं जानता है।

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

आगे, फ़ील्ड और गुणों के बीच प्रदर्शन अंतर वर्ग संरचनाओं की तुलना में बड़ी संरचनाओं के साथ बहुत अधिक है। दरअसल, बड़ी संरचनाओं से बचने की सिफारिश में से अधिकांश इस अंतर का परिणाम है। बड़ी संरचनाएं वास्तव में बहुत ही कुशल हो सकती हैं, अगर कोई उन्हें अनावश्यक रूप से कॉपी करने से बचाता है। यहां तक ​​कि अगर एक एक विशाल संरचना HexDecet<HexDecet<HexDecet<Integer>>>, जहां HexDecet<T> क्षेत्रों F0 उजागर निहित .. प्रकार T की F15, Foo = MyThing.F3.F6.F9; की तरह एक बयान बस MyThing से एक पूर्णांक पढ़ने की आवश्यकता होती है जाएगा और Foo को संग्रहित करना, यहां तक ​​कि MyThing होगा विशाल द्वारा struct मानकों के द्वारा (हालांकि था 166 पर कब्जा कर लिया 4096 पूर्णांक)। इसके अतिरिक्त, कोई उस तत्व को बहुत आसानी से अपडेट कर सकता है, उदा। MyThing.F3.F6.F9 += 26;। इसके विपरीत, अगर F0 .. F15 थे ऑटो गुण, बयान 4 बाइट पढ़ने के लिए Foo = MyThing.F3.F6.F9 एक अस्थायी (इसे कहते temp1, तो 64 temp1.F6 से temp2 के लिए डेटा के बाइट्स) अंत में चारों ओर हो रही से पहले करने के लिए MyThing.F3 से डेटा के 1K को कॉपी की आवश्यकता होगी temp2.F9 से डेटा का। Ick। इससे भी बदतर, MyThing.F3.F6.F9 में मान में 26 जोड़ने की कोशिश करने के लिए var t1 = MyThing.F3; var t2 = t1.F6; t2.F9 += 26; t1.F6 = f2; MyThing.F3 = t1; जैसे कुछ की आवश्यकता होगी।

"उत्परिवर्तनीय संरचना प्रकार" के बारे में लंबे समय से चलने वाली शिकायतों में से कई वास्तव में पढ़ने/लिखने वाले गुणों के साथ संरचना प्रकारों के बारे में शिकायतें हैं। बस फ़ील्ड के साथ गुणों को प्रतिस्थापित करें और समस्याएं दूर हो जाएं।

पीएस: कई बार ऐसे संरचना के लिए उपयोगी हो सकता है जिनके गुण एक वर्ग ऑब्जेक्ट तक पहुंचते हैं जिसके संदर्भ में यह संदर्भ होता है। उदाहरण के लिए, ArraySegment<T> वर्ग का संस्करण होना अच्छा लगेगा, जिसने Var foo[] = new int[100]; Var MyArrSeg = New ArraySegment<int>(foo, 25, 25); MyArrSeg[6] += 9; कहने की अनुमति दी है, और अंतिम विवरण foo के तत्व (25 + 6) में नौ जोड़ता है। सी # के पुराने संस्करणों में ऐसा हो सकता है। दुर्भाग्यवश, फ्रेमवर्क में ऑटोप्रोपर्टीज का लगातार उपयोग जहां खेतों में अधिक उपयुक्त होता, संकलक के बारे में व्यापक शिकायतों का कारण बनता है जिससे संपत्ति सेटर्स को केवल पढ़ने-योग्य संरचनाओं पर बेकार कहा जा सकता है; नतीजतन, किसी भी प्रॉपर्टी सेटर को केवल पढ़ने-योग्य संरचना पर कॉल करना अब प्रतिबंधित है, चाहे संपत्ति सेटटर वास्तव में संरचना के किसी भी क्षेत्र को संशोधित करेगा या नहीं। अगर लोगों ने संपत्ति सेटर्स के माध्यम से structs mutable बनाने से बस बचना था (म्यूटेबिलिटी उचित होने पर फ़ील्ड सीधे पहुंच योग्य बनाते हैं) कंपाइलर्स को उस प्रतिबंध को कभी लागू नहीं करना पड़ेगा।

संबंधित मुद्दे

 संबंधित मुद्दे