केवल गटर के साथ स्वचालित संपत्ति, सेट किया जा सकता है, क्यों?


96

मैंने एक स्वचालित संपत्ति बनाई:

public int Foo { get; } 

यह केवल गटर है। लेकिन जब मैं एक निर्माता का निर्माण करता हूं, तो मैं मूल्य बदल सकता हूं:

public MyClass(string name)
{
    Foo = 5;
}

यह संभव है, भले ही यह केवल प्राप्त हो?


यह वास्तव में एक सेटर का उपयोग नहीं करता है (क्योंकि इसमें एक नहीं है)। यह सीधे अंतर्निहित क्षेत्र को सेट करता है (जो हमसे छिपा हुआ है, यही वजह है कि आपको संपत्ति के नाम का उपयोग करने की आवश्यकता है)
डेनिस_ई

14
एक संपत्ति का क्या उपयोग है, अगर इसे कभी भी प्रारंभ / सेट नहीं किया जा सकता है? याकूब
मस्साद

जवाबों:


123

यह एक नया C # 6 फीचर है, "गेट-ओनली ऑटो-प्रॉपर्टीज", जिसे "MS-only प्रॉपर्टीज फॉर रीड-ओनली प्रॉपर्टीज" के रूप में भी जाना जाता है, जैसा कि इस MSDN मैगज़ीन के लेख 'C #: द न्यू एंड इम्प्रूव्ड C # 6.0' में चर्चा की गई है। माइकलिस और सी # 6.0 ड्राफ्ट लैंग्वेज स्पेसिफिकेशन में

रीड-ओनली फ़ील्ड का सेटर केवल कंस्ट्रक्टर में ही सुलभ है, अन्य सभी स्थितियों में फ़ील्ड को अभी भी केवल पढ़ा जाता है और पहले की तरह व्यवहार करता है।

यह एक सुविधा सिंटैक्स है जो आपको कोड की मात्रा को कम करने और मान रखने के लिए एक निजी मॉड्यूल स्तर चर को स्पष्ट रूप से घोषित करने की आवश्यकता को दूर करने के लिए है।

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

यह ब्लॉग पोस्ट, शॉन सेक्सटन द्वारा '# 1,207 - C # 6.0 - ऑटो-प्रॉपर्टी इनिशियलाइजर्स फॉर रीड-ओनली प्रॉपर्टीज' की अच्छी व्याख्या और उदाहरण निम्नानुसार है:

C # 6.0 से पहले, यदि आप एक रीड-ओनली (अपरिवर्तनीय) प्रॉपर्टी चाहते थे, तो आप आमतौर पर रीड-ओनली बैकिंग फ़ील्ड का उपयोग करेंगे, जो कि कंस्ट्रक्टर में आरंभीकृत है, जैसा कि नीचे दिखाया गया है।

public class Dog 
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }

    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

C # 6.0 में, आप केवल-पढ़ने के लिए गुण लागू करने के लिए ऑटो-कार्यान्वित गुणों का उपयोग कर सकते हैं। आप एक ऑटो-प्रॉपर्टी इनिशियलाइज़र का उपयोग करके ऐसा करते हैं। परिणाम उपरोक्त उदाहरण की तुलना में बहुत साफ है, जहां हमें स्पष्ट रूप से एक समर्थन क्षेत्र घोषित करना था।

public class Dog
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;

    public Dog(string name)
    {
        Name = name;
    }
}

GitHub पर डॉटनेट रोज़लिन रेपो में अधिक जानकारी भी प्राप्त की जा सकती है :

ऑटो-प्रॉपर्टीज को अब बिना सेटर के घोषित किया जा सकता है।

एक गेट-ओनली ऑटो-प्रॉपर्टी के बैकिंग क्षेत्र को स्पष्ट रूप से आसानी से घोषित किया जाता है (हालांकि यह केवल प्रतिबिंब उद्देश्यों के लिए मायने रखता है)। इसे प्रॉपर्टी पर इनिशियलाइज़र के माध्यम से शुरू किया जा सकता है जैसा कि ऊपर दिए गए उदाहरण में है। इसके अलावा, एक गेट-ओनली प्रॉपर्टी को घोषित प्रकार के कंस्ट्रक्टर बॉडी में सौंपा जा सकता है, जिससे मूल्य सीधे अंतर्निहित क्षेत्र को सौंपा जा सकता है:

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

और C # 6.0 ड्राफ्ट लैंग्वेज स्पेसिफिकेशन (NB: भाषा विनिर्देश Microsoft के संबंध में अंतिम है, लेकिन इसे EMCA / ISO मानक के रूप में अनुमोदित किया जाना बाकी है , इसलिए 'ड्राफ्ट'):

स्वचालित रूप से लागू गुण

स्वचालित रूप से कार्यान्वित की गई संपत्ति (या शॉर्ट के लिए ऑटो-प्रॉपर्टी), अर्धविराम केवल एक्सेसर निकायों के साथ एक गैर-अमूर्त गैर-बाहरी संपत्ति है। ऑटो-संपत्तियों में एक एक्सेस एक्सेसर होना चाहिए और वैकल्पिक रूप से एक सेट एक्सेसर हो सकता है।

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

एक ऑटो-प्रॉपर्टी में वैकल्पिक रूप से एक प्रॉपर्टी_इन्टिलाइज़र हो सकता है, जो सीधे बैकिंग फ़ील्ड पर एक वैरिएबल_इनिशिएलाइज़र (वेरिएबल इनिशियलाइज़र) के रूप में लागू होता है।


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

मेरे लिए अजीब बात यह है कि एक कंपाइलर त्रुटि है जो CS0200 C# Property or indexer cannot be assigned to -- it is read onlyनियमित संपत्ति का उपयोग करते समय कहती है। क्या "गेट-ओनली ऑटो-प्रॉपर्टीज" को केवल पढ़ने के लिए माना जाता है या नहीं?
काइल डेलानी

24

यह C # 6 में एक नई विशेषता है जो आपको केवल-पढ़ने के लिए गुण बनाने और निर्माण (या जब आप उन्हें घोषित करते हैं तो इनलाइन) से उनके मूल्यों को आरंभ करने की अनुमति देता है।

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

यह केवल इस अर्थ में पढ़ा जाता है कि एक बार जब आप इसके मूल्य (इनलाइन या कंस्ट्रक्टर के अंदर) को इनिशियलाइज़ कर लेते हैं, तो आप इसका मान नहीं बदल सकते।


तो, स्पष्टीकरण क्या है? एक गटर की परिभाषा क्या है?
नोआम बी।

16

यदि कंस्ट्रक्टर (या ऑटो-प्रॉपर्टी इनिशियलाइज़र) से रीड-ओनली प्रॉपर्टी को इनिशियलाइज़ करना संभव नहीं था, तो यह बेकार होगा, क्योंकि यह हमेशा अपने टाइप के लिए डिफॉल्ट वैल्यू लौटाएगा (0 के लिए न्यूमेरिक्स, रेफरेंस टाइप्स के लिए शून्य) )। एक ही अर्थ विज्ञान के लिए लागू केवल पढ़ने के लिए सभी सी # संस्करणों में खेतों।

एक सच्चे गेट-ओनली प्रॉपर्टी को परिभाषित करने के लिए (जिसे कंस्ट्रक्टर से इनिशियलाइज़ नहीं किया जा सकता है), आपको यह निर्दिष्ट करने की आवश्यकता है कि यह परिभाषा के हिस्से के रूप में क्या लौटाता है:

public int Foo { get { return 5; } }

या, अधिक संक्षेप में C # 6 में:

public int Foo => 5;

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

3
@ सेबागोमेज़: मुझे यकीन नहीं है कि मैं आपकी बात मान रहा हूँ - क्या यह नहीं है कि मैंने अपने उदाहरण में क्या प्रदर्शित किया है?
डगलस

5

"आसानी से स्वचालित रूप से लागू गुण"

सबसे पहले मैं यह स्पष्ट करना चाहता हूं कि संपत्ति पसंद है

public string FirstName { get; }

के रूप में जाना जाता है "आसानी से स्वचालित रूप से लागू गुण"

इसे सत्यापित करने के लिए आप विजुअल स्टूडियो के साथ उपरोक्त कोड को चला सकते हैं और जांच सकते हैं। यदि आप भाषा संस्करण को C # 6.0 से C # 5.0 में बदलते हैं, तो संकलक निम्न अपवाद को फेंक देगा फ़ीचर 'आसानी से स्वचालित रूप से कार्यान्वित गुण' C # 5 में उपलब्ध नहीं है। कृपया भाषा संस्करण 6 या अधिक का उपयोग करें।

सी # भाषा संस्करण बदलने के लिए यहां जाएं

अब मैं आपके दूसरे प्रश्न पर आ रहा हूं

“यह केवल गटर है। लेकिन जब मैं एक निर्माता का निर्माण करता हूं, तो मैं मूल्य बदल सकता हूं ”

Microsoft केवल पढ़ने के तर्क पर "स्वचालित रूप से कार्यान्वित किए गए गुण" का परिचय देता है। जैसा कि हम जानते हैं कि कीवर्ड "आसानी से" C # 1.0 से उपलब्ध है। हम का उपयोग करें "केवल पढ़ने के लिए" एक क्षेत्र पर संशोधक और उस क्षेत्र के रूप में कीवर्ड में सौंपा जा सकता है 2 तरीके या तो घोषणा के समय में या एक ही कक्षा में एक निर्माता में।

उसी तरह से "स्वचालित रूप से कार्यान्वित किए गए गुण" का मान 2 तरीकों से सौंपा जा सकता है

Way1 (घोषणा के समय):

public string FirstName { get; } = "Banketeshvar";

Way2 (एक ही कक्षा में एक निर्माता)

Person()
{
 FirstName  = "Banketeshvar";
}

विशुद्ध रूप से ReadOnly संपत्ति

यदि आप विशुद्ध रूप से Readonly संपत्ति की तलाश कर रहे हैं तो इसके लिए जाएं

public string FullName => "Manish Sharma";

अब आप कन्स्ट्रक्टर से "FullName" की वैल्यू असाइन नहीं कर सकते। यदि आप यह करने की कोशिश करते हैं कि यह निम्नलिखित अपवादों को फेंक देगा

"प्रॉपर्टी या इंडेक्सर 'पर्सन.फूलनाम' को नहीं सौंपा जा सकता है - यह केवल पढ़ा जाता है"


2
ध्यान दें कि FullName => "foo bar" का मूल्यांकन हर समय किया जाएगा।
जूफो ३१'१

4

C # 3.0 रिलीज़ के दौरान भाषा में ऑटो गुण सुविधा जोड़ी गई थी। यह आपको किसी भी बैकिंग फ़ील्ड के बिना एक संपत्ति को परिभाषित करने की अनुमति देता है, हालांकि आपको अभी भी इन ऑटो गुणों को गैर-डिफ़ॉल्ट मान के लिए आरम्भ करने के लिए कंस्ट्रक्टर का उपयोग करने की आवश्यकता है। C # 6.0 एक नया फीचर पेश करता है, जिसे ऑटो प्रॉपर्टी इनिशियलाइज़र कहा जाता है, जो आपको नीचे दिए गए कंस्ट्रक्टर के बिना इन गुणों को इनिशियलाइज़ करने की अनुमति देता है:

इससे पहले, एक कंस्ट्रक्टर की आवश्यकता होती है यदि आप ऑटो-प्रॉपर्टी का उपयोग करके ऑब्जेक्ट बनाना चाहते हैं और नीचे की तरह एक नॉन-डिफॉल्ट मान के लिए एक ऑटो-प्रॉपर्टी को इनिशियलाइज़ करते हैं:

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}

अब C # 6.0 में, ऑटो-प्रॉपर्टी के साथ इनिशलाइज़र का उपयोग करने की क्षमता का मतलब है कि कोई स्पष्ट कंस्ट्रक्टर कोड की आवश्यकता नहीं है।

public string Foo { get; } = "SomeString";

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

आप इस पर अधिक जानकारी यहाँ पा सकते हैं


1

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

जिस प्रकार पठन-लेखन ऑटो-गुण मौजूद है, वह वर्गों को उत्परिवर्तित गुणों को आसानी से सामान्य क्षेत्रों के रूप में उजागर करने की अनुमति देता है, केवल-पढ़ने के लिए ऑटो-गुण मौजूद है ताकि वर्गों को आसानी से अयोग्य गुणों को उजागर करने की अनुमति मिल सके readonly। जिस तरह readonly-क्वालिफाइड फील्ड्स को कंस्ट्रक्टर में लिखा जा सकता है, उसी तरह गेट-ओनली प्रॉपर्टीज के साथ भी।

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