2016-01-12 14 views
61

मैं एक स्वचालित संपत्ति बनाई। लेकिन जब मैं एक निर्माता का निर्माण, मैं मान परिवर्तित कर सकते हैं:केवल गेटटर के साथ स्वचालित संपत्ति सेट की जा सकती है, क्यों?</p> <pre><code>public int Foo { get; } </code></pre> <p>यह केवल गेटर है:

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

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

+0

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

+10

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

उत्तर

81

यह एक नई सी # 6 सुविधा, "मनुष्य-केवल ऑटो-गुण", के रूप में यह MSDN magazine article 'C# : The New and Improved C# 6.0' by Mark Michaelis में और C# 6.0 draft Language Specification में चर्चा भी "केवल पढ़ने के लिए गुण के लिए ऑटो-संपदा initializers" के रूप में जाना जाता है।

केवल पढ़ने के लिए फ़ील्ड का सेटटर केवल कन्स्ट्रक्टर में ही पहुंच योग्य है, अन्य सभी परिदृश्यों में फ़ील्ड अभी भी पढ़ा जाता है और पहले जैसा व्यवहार करता है।

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

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

This blog post, '#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties' by Sean Sexton इस प्रकार एक अच्छा विवरण और उदाहरण है:

पहले सी # 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; 
    } 
} 

सी # 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; 
    } 
} 

अधिक जानकारी भी the dotnet Roslyn repo on GitHub में पाया जा सकता:

ऑटो गुण अब एक सेटर बिना घोषित किया जा सकता।

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

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

और C# 6.0 draft Language Specification में:

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

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

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

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

+0

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

22

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

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

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

+0

तो, स्पष्टीकरण क्या है? गेटटर की परिभाषा क्या है? –

+1

यह एक रीडोनली फ़ील्ड – pseudoDust

4

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

इससे पहले, एक निर्माता के लिए आवश्यक है कि आप वस्तुओं एक स्वत: संपत्ति का उपयोग कर बना सकते हैं और एक को प्रारंभ करना चाहते हैं: सी # 6.0 एक नई सुविधा बुलाया ऑटो संपत्ति प्रारंभकर्ता जो आप एक निर्माता की तरह नीचे के बिना इन गुणों को प्रारंभ करने की अनुमति देता का परिचय एक गैर-सामान्य मान नीचे की तरह करने के लिए स्वत: संपत्ति:

public class MyClass 
{ 
    public int Foo { get; } 

    public Foo(int foo) 
    { 
     Foo = foo; 
    } 
} 
अब सी # 6.0 में

, ऑटो संपत्ति के साथ एक प्रारंभकर्ता उपयोग करने की क्षमता नहीं explici का मतलब टी कन्स्ट्रक्टर कोड की आवश्यकता है।

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

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

You can find more information on this here

10

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

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

public int Foo { get { return 5; } } 

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

public int Foo => 5; 
+0

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

+1

@sebagomez पढ़ते हैं तो उचित मान वापस कर सकते हैं: मुझे यकीन नहीं है कि मुझे आपका अंक मिल रहा है - यह नहीं है कि मैं मेरे उदाहरण में प्रदर्शित किया? – Douglas

1

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

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

3

"केवल पढ़ने के लिए स्वचालित रूप से लागू किया गुण"

सबसे पहले मैं स्पष्ट करने के लिए इस तरह

public string FirstName { get; } 

संपत्ति के रूप में "केवल पढ़ने के लिए स्वचालित रूप से लागू किया गुण"

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

सी # भाषा संस्करण यात्रा here

अब मैं अपने दूसरे प्रश्न

आ रही हूँ बदलने के लिए "यह केवल मनुष्य है। लेकिन जब मैं एक कन्स्ट्रक्टर बनाता हूं, तो मैं मान बदल सकता हूं "

माइक्रोसॉफ्ट केवल पढ़ने के तर्क पर" केवल स्वचालित रूप से कार्यान्वित गुणों "को प्रस्तुत करता है। जैसा कि हम जानते हैं कि कीवर्ड "readonly" सी # 1.0 से उपलब्ध है। हम एक क्षेत्र में संशोधक के रूप में "readonly" कीवर्ड का उपयोग करते हैं और उस क्षेत्र को 2 तरीके या तो घोषित करने के समय या उसी श्रेणी में एक निर्माता में असाइन किया जा सकता है।(

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

Way2 एक में:

"केवल पढ़ने के लिए स्वचालित रूप से लागू किया गुण" का एक ही तरह से मूल्य में 2 तरीके

Way1 (घोषणा के समय) में सौंपा जा सकता है एक ही कक्षा में कन्स्ट्रक्टर)

Person() 
{ 
FirstName = "Banketeshvar"; 
} 

शुद्ध रूप से केवल पठनीय संपत्ति

आप विशुद्ध रूप से केवल पढ़ने के लिए संपत्ति के लिए देख रहे हैं तो यह

public string FullName => "Manish Sharma"; 

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

फेंक होगा करने की कोशिश करते हैं "संपत्ति या इंडेक्सर 'Person.FullName' को सौंपा नहीं जा सकता है - यह केवल पढ़ने के लिए"

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