.NET गुण - निजी सेट या ReadOnly संपत्ति का उपयोग करें?


45

किस स्थिति में मुझे किसी प्रॉपर्टी पर प्राइवेट सेट का इस्तेमाल करना चाहिए। नीचे दिए गए दो बहुत ही सरल उदाहरणों पर विचार करें।

पहला उदाहरण:

Public Class Person

    Private _name As String

    Public Property Name As String
        Get
            Return _name
        End Get
        Private Set(ByVal value As String)
            _name = value
        End Set
    End Property

    Public Sub WorkOnName()

        Dim txtInfo As TextInfo = _
            Threading.Thread.CurrentThread.CurrentCulture.TextInfo

        Me.Name = txtInfo.ToTitleCase(Me.Name)

    End Sub

End Class

// ----------

public class Person
{
    private string _name;
    public string Name
    {
        get { return _name; }
        private set { _name = value; }
    }

    public void WorkOnName()
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        this.Name = txtInfo.ToTitleCase(this.Name);
    }
}

दूसरा उदाहरण:

Public Class AnotherPerson

    Private _name As String

    Public ReadOnly Property Name As String
        Get
            Return _name
        End Get
    End Property

    Public Sub WorkOnName()

        Dim txtInfo As TextInfo = _
            Threading.Thread.CurrentThread.CurrentCulture.TextInfo

        _name = txtInfo.ToTitleCase(_name)

    End Sub

End Class

// ---------------

public class AnotherPerson
{
    private string _name;
    public string Name
    {
        get { return _name; }
    }

    public void WorkOnName()
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        _name = txtInfo.ToTitleCase(_name);
    }
}

वे दोनों एक ही परिणाम देते हैं। क्या यह ऐसी स्थिति है जहाँ कोई सही और गलत नहीं है, और यह सिर्फ वरीयता का मामला है?


public string Name { get; protected set; }वंशानुक्रम के माध्यम से।
samis

जवाबों:


42

उपयोग करने के लिए कुछ कारण हैं private set

1) यदि आप एक बैकिंग क्षेत्र का उपयोग नहीं कर रहे हैं और केवल-पढ़ने के लिए स्वचालित संपत्ति चाहते हैं:

public string Name { get; private set; }   

public void WorkOnName()
{
    TextInfo txtInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
    Name = txtInfo.ToTitleCase(Name);
}  

2) यदि आप अपनी कक्षा के अंदर चर को संशोधित करते समय अतिरिक्त कार्य करना चाहते हैं और एक ही स्थान पर कब्जा करना चाहते हैं:

private string _name = string.Empty;
public string Name 
{ 
    get { return _name; }
    private set 
    {
        TextInfo txtInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
        _name = txtInfo.ToTitleCase(value);
    }
}

सामान्य तौर पर, हालांकि, यह व्यक्तिगत प्राथमिकता की बात है। जहाँ तक मुझे पता है, एक के बाद एक प्रयोग करने के कोई प्रदर्शन कारण नहीं हैं।


1
बस इसे जोड़ते हुए क्योंकि प्रश्न में vb.net टैग भी है, लेकिन vb.net में आपको एक बैकर निर्दिष्ट करने की आवश्यकता है यदि आप या तो निजी उपयोग करते हैं या सेट करते हैं। इसलिए vb.net में यह वास्तव में कम संपत्ति बनाने के लिए काम करता है जो मुझे लगता है।
user643192

मुझे उसके बारे में कभी पता नहीं था private set। :-)
अफ़ज़ल अहमद ज़ीशान

9
2016 में इस उत्तर को पढ़ने वालों के लिए एक अपडेट। सी # 6.0 ने आसानी से ऑटो-गुण पेश किए हैं, जो आपको एक बैकिंग क्षेत्र के बिना आसानी से संपत्ति प्राप्त करने की अनुमति देते हैं public string Name { get; }:। यदि आप एक परिवर्तनशील संपत्ति नहीं चाहते हैं, तो वह पसंदीदा सिंटैक्स है।
एलेक्सी

4
उपयोग न करने का एक बहुत अच्छा कारण यह private setहै कि यह उतना अपरिवर्तनीय नहीं है जितना हम इसे पसंद करते हैं। यदि आप वास्तव में अपरिवर्तनीय वर्ग को लागू करना चाहते हैं, तो केवल पढ़ना आवश्यक है।
रबरडक

आसानी से उपयोग नहीं करने के लिए एक प्रदर्शन कारण हो सकता है। जब एक पठनीय संरचना क्षेत्र के तरीकों का उपयोग करते हुए संरचनाओं की अनावश्यक नकल का कारण बनता है। codeblog.jonskeet.uk/2014/07/16/…
Triynko

28

जब आप सेटर को बाहर से एक्सेस नहीं कर सकते, तो निजी सेट का उपयोग करें ।

का प्रयोग करें केवल पढ़ने के लिए जब आप करना चाहते हैं केवल एक बार गुण सेट । कंस्ट्रक्टर या वैरिएबल इनिशियलाइज़र में।

परीक्षण इस:

void Main()
{
    Configuration config = new Configuration();
    config.ResetConfiguration();

    ConfigurationReadOnly configRO = new ConfigurationReadOnly();
    configRO.ResetConfiguration();
}

public class Configuration
{
    public Color BackgroundColor { get; private set; }
    public Color ForegroundColor { get; private set; }
    public String Text { get; private set; }

    public Configuration()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }

    public void ResetConfiguration()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }
}

public class ConfigurationReadOnly
{
    public readonly Color BackgroundColor;
    public readonly Color ForegroundColor;
    public readonly String Text;

    public ConfigurationReadOnly()
    {
        BackgroundColor = Color.Black;
        ForegroundColor = Color.White;
        Text = String.Empty;
    }

    public void ResetConfiguration()
    {
        BackgroundColor = Color.Black; // compile error: due to readonly keyword
        ForegroundColor = Color.White; // compile error: due to readonly keyword
        Text = String.Empty; // compile error: due to readonly keyword
    }
}

जबकि मैं आपके उत्तर से सहमत हूं, आपका उदाहरण कुछ सुधार का उपयोग कर सकता है। आप एक टिप्पणी करना चाहते हैं कि संकलक त्रुटि कहाँ होगी।
माइकल रिचर्डसन

NB C # readonlyकीवर्ड के अनुरूप VB.NET सिंटैक्स , ReadOnlyगुण के बजाय फ़ील्ड पर लागू होता है।
ज़ेव स्पिट्ज

8

क्या मैं तीसरा विकल्प सुझा सकता हूं?

public class Person
{
    public string Name { get; protected set; }

    public void SetName(string name)
    {
        TextInfo txtInfo = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
        this.Name = txtInfo.ToTitleCase(name);
    }
}

यह नाम संपत्ति को प्रभावी रूप से केवल सभी बाहरी कोड के लिए पढ़ता है और एक स्पष्ट सेट विधि प्रदान करता है। मैं नाम संपत्ति पर सेट का उपयोग करने के बजाय स्पष्ट सेट पसंद करता हूं क्योंकि आप इसे सेट करते समय मूल्य बदल रहे हैं। आम तौर पर यदि आप एक संपत्ति मूल्य निर्धारित करते हैं, तो आप उसी मूल्य को वापस पाने की उम्मीद करते हैं जब आप बाद में कॉल प्राप्त करते हैं, जो कि अगर आपने सेट में अपना टेटिटेलकेस किया तो ऐसा नहीं होगा ।

हालाँकि, जैसा कि आपने कहा, कोई सही उत्तर नहीं है।


मेरा मानना ​​है कि संकलक में 'निजी सेट' का विशेष शब्दार्थ होता है (केवल निजी अभिगमकर्ता के रूप में नहीं)। यह भी संरक्षित सेट के साथ मामला है? यदि नहीं, तो निजी सेट विशेष शब्दार्थ होने पर संरक्षित सेट के बराबर सिमेंटिक कहाँ है? मैं इसे समझाते हुए कोई दस्तावेज नहीं ढूंढ पाया।
स्प्रैग

1
+1 लेकिन मैं "SetName" के बजाय "Rename" विधि कहूँगा।
मैटवेवी

5

C # 6.0 में शुरू, गेट्टर-ओनली ऑटो प्रॉपर्टीज को भाषा में जोड़ा गया है। यहां देखें: https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#getter-only-auto-properties

यहाँ एक उदाहरण है:

public class SomeClass
{
    public int GetOnlyInt { get; }

    public int GetOnlyIntWithInitializer { get; } = 25;

    public SomeClass(int getOnlyInt)
    {
        GetOnlyInt = getOnlyInt;
    }
}

4

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

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


2

जब भी मुझे किसी सेटर के एक्सेस स्तर को बदलने की आवश्यकता होती है, तो मैंने इसे आमतौर पर या तो प्रोटेक्टेड में बदल दिया है (केवल यह वर्ग और व्युत्पन्न वर्ग मान बदल सकते हैं) या मित्र (मेरी विधानसभा के सदस्य ही मूल्य बदल सकते हैं)।

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


0

और वस्तुतः कोई प्रदर्शन दंड नहीं है ...

लेकिन स्पष्ट करने के लिए, किसी प्रॉपर्टी को एक्सेस करना उसके बैकिंग वैरिएबल तक पहुंचने की तुलना में धीमा है। प्रॉपर्टी का गेट्टर और सेटर ऐसे तरीके हैं, जिनमें कॉल और रिटर्न की आवश्यकता होती है, जबकि प्रॉपर्टी का बैकिंग वेरिएबल सीधे एक्सेस किया जाता है।

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

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