क्या मुझे निजी क्षेत्रों के साथ या बिना संपत्तियों को प्राथमिकता देना चाहिए?


16

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

// Fields
private double _foo;
private double _bar;
private double _baz;

// Properties
public double Foo
{
    get{ return _foo; }
    set{ _foo = value; }
}

public double Bar
{
    get{ return _bar; }
    set{ _bar = value; }
}

public double Baz
{
    get{ return _baz; }
}

मुझे पता है कि ये उनके आंतरिक निजी गुणों के बिना फिर से लिखे जा सकते हैं:

public double Foo{ get; set; }
public double Bar{ get; set; }
public double Baz{ get; private set; }

मुझे इस पर कुछ इनपुट चाहिए:

  • क्या पुराने, अधिक स्पष्ट शैली को नए, अधिक संक्षिप्त रूप से पसंद करने का एक अच्छा कारण है?
  • क्या मुझे संक्षिप्त शैली का उपयोग करके कोई नई कक्षाएं लिखनी चाहिए, या क्या मुझे निरंतरता के लिए पुराने कोड से मेल खाने की कोशिश करनी चाहिए? क्या पुराने प्रारूप को सही ठहराने के लिए इस मामले में पर्याप्तता है?


@PeterK। जानकारीपूर्ण। यह जवाब नहीं देता कि मुझे बाकी कार्यक्रम की शैली के साथ रखने के बारे में चिंता करनी चाहिए या नहीं, या अगर यह एक छोटा सा पर्याप्त विवरण है, हालांकि यह बात नहीं है।
KChaloux

@ केचलौक्स: समझ गया! इसलिए यह एक टिप्पणी है, एक जवाब नहीं है। :-)
पीटर के।

@PeterK। Fair 'nuff = p
KChaloux

1
बदलने का एक और कारण यह है कि अगर WCF के साथ तार पर कुछ भी पारित किया जाता है - स्वचालित गुणों में अनुबंध के मुद्दे हैं (.NET द्वारा बनाए गए बैकिंग फ़ील्ड नामों में अमान्य वर्णों के कारण)
लियोन

जवाबों:


16

कुछ उदाहरण हैं जहां तथाकथित "पुरानी" शैली अभी भी आवश्यक है:

ए: भाषा-प्रदान की अपरिवर्तनीयता का उपयोग कर अपरिवर्तनीय प्रकार। readonlyसी # में संशोधक निर्माण के बाद कि मूल्य जमा। स्वचालित रूप से लागू गुणों (अभी तक) के साथ इस की नकल करने का कोई तरीका नहीं है।

public sealed class FooBarBazInator
{
    private readonly double foo;

    public FooBarBazInator(double foo)
    {
        this.foo = foo;
    }

    public double Foo
    {
        get
        {
            return this.foo;
        }
    }
}

B: आपके गेटर्स / सेटर्स में कोई भी तर्क हो। WPF और सिल्वरलाइट (और समान) कोड जो आपकी कक्षाओं के लिए डेटा-बाउंड हैं INotifyPropertyChanged, वे इस तरह लागू होंगे :

public class FooBarBazInator : INotifyPropertyChanged
{
    private double foo;

    public event PropertyChangedEventHandler PropertyChanged;

    public double Foo
    {
        get
        {
            return this.foo;
        }

        set
        {
            this.foo = value;
            this.RaisePropertyChanged("Foo");
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

उन लोगों के अलावा, मैं कहूंगा कि नई शैली का उपयोग करें। अपने कोड को संक्षिप्त रखता है और बग को रेंगने के लिए कम सतह वाला क्षेत्र प्रदान करता है। इसके अलावा, यदि इसे तर्क को शामिल करने के लिए कभी भी बदलने की आवश्यकता होती है, तो यह हस्ताक्षर-असंगत नहीं होगा।


2
हर कोई नई शैली के साथ जाने के बारे में सहमति देता है। आपको readonlyमॉडिफ़ायर के साथ एक फ़ील्ड की आवश्यकता के बारे में बताने के लिए आपको +1 और उत्तर क्रेडिट मिलता है , जो मुझे नहीं पता था। = डी
KChaloux

3
कुछ (मेरे सहित) अपरिवर्तनीय गुणों के लिए निजी एक्सेसर के साथ ऑटो गुणों को "अच्छा पर्याप्त" मानते हैं। सच है, वे वास्तव में अपरिवर्तनीय नहीं हो सकते हैं, लेकिन आपको बस सावधान रहना होगा कि कंस्ट्रक्टर के बाहर सेटर का उपयोग न करें।
svick

2
एक और रीऑन है यदि आप उस मान को पास करना चाहते हैं refजो गुणों के साथ काम नहीं करता है, तो आपको फ़ील्ड की आवश्यकता है
stijn

1
INotifyPropertyChangedस्पष्ट बैकिंग फ़ील्ड की आवश्यकता के बिना Fody जैसा टूल लागू हो सकता है । github.com/Fody/PropertyChanged
सेबेस्टियन रेडल

3
ध्यान दें: C # 6 "गेट्टर-ओनली ऑटो-प्रॉपर्टीज" के लिए अनुमति देता है जो एक ही लाइन में प्रदान करता है कि मेरा उदाहरण "ए" क्या कर रहा है।
जेसी सी। स्लाइसर

6

मैं कहूंगा कि स्पष्ट बैकिंग फ़ील्ड का होना बेकार है: यह आपके कोड को पढ़ने में अधिक लंबा और कठिन बनाता है। यह त्रुटि की क्षमता भी जोड़ता है:

public double Bar
{
    get { return _baz; }
    set { _bar = value; }
}

मुझे लगता है कि इस तरह की एक त्रुटि काफी आसानी से हो सकती है और स्पॉट करना काफी कठिन होगा।

और यदि आप स्थिरता चाहते हैं, तो इसे दूसरे तरीके से करें: कोड बदलें जो बैकिंग फ़ील्ड का उपयोग कोड में करता है जो स्वचालित गुणों का उपयोग करता है। यह विशेष रूप से आसान है यदि आप रीफ़ेयरिंग उपकरण जैसे रीशर (और यदि आप ऐसा कुछ उपयोग नहीं करते हैं, तो मुझे लगता है कि आपको शुरू करना चाहिए)।

बेशक, अभी भी ऐसे मामले हैं जहां बैकिंग फील्ड होना आवश्यक है, लेकिन मुझे लगता है कि यह इस प्रश्न के लिए प्रासंगिक नहीं है।


मैंने वास्तव में कुछ पुराने क्षेत्रों पर किया है जब कोड को रीफैक्टरिंग कर रहा है ... यह एक दर्द है।
KChaloux

1

हालांकि यह सवाल काफी पुराना है, लेकिन मैंने उन दो बिंदुओं को जोड़ने के बारे में सोचा, जिन्हें मैं यहां उल्लेख के लायक किताब से पढ़ता हूं।

  1. रन-टाइम क्रमांकन इंजन क्रमबद्ध स्ट्रीम में दायर किए गए नाम को जारी रखता है। स्वचालित रूप से कार्यान्वित की गई संपत्ति (AIP) के लिए बैकिंग फ़ील्ड का नाम कंपाइलर द्वारा निर्धारित किया जाता है, और यह वास्तव में इस बैकिंग फ़ील्ड का नाम बदल सकता है हर बार जब आप अपने कोड को recompile करते हैं, तो किसी भी प्रकार के इंस्टेंसेस के deserialize करने की क्षमता को नकारने में AIP। इसलिए AIP का उपयोग किसी भी प्रकार के साथ न करें, जिसे आप क्रमबद्ध या अस्वाभाविक बनाना चाहते हैं।

  2. डिबगिंग करते समय, आप एआईपी गेट या सेट विधि पर एक ब्रेकपॉइंट नहीं डाल सकते हैं, इसलिए आप आसानी से पता नहीं लगा सकते हैं कि आवेदन कब मिल रहा है या इस संपत्ति को सेट करें। आप मैन्युअल रूप से कार्यान्वित ब्रेकपॉइंट पर ब्रेकपॉइंट सेट कर सकते हैं


3
# 1 - अधिकांश धारावाहिक डिफ़ॉल्ट रूप से निजी गुणों / क्षेत्रों की उपेक्षा करते हैं; आपके द्वारा बताए गए मुद्दों का मैंने कभी सामना नहीं किया। # 2 - यह VS2015 में तय किया गया है और इसे VS2013 में काम किया जा सकता है। देखें इस दृश्य स्टूडियो पत्रिका लेख
ब्रायन

-3

क्या पुराने, अधिक स्पष्ट शैली को नए, अधिक संक्षिप्त रूप से पसंद करने का एक अच्छा कारण है?

ज़रुरी नहीं। हालांकि मैं तर्क दूंगा कि किसी भी समय आपके पास उस तरह की संपत्ति थी, जिसे शुरू करने के लिए आपको सार्वजनिक क्षेत्र का उपयोग करना चाहिए था।

क्या मुझे संक्षिप्त शैली का उपयोग करके कोई नई कक्षाएं लिखनी चाहिए, या क्या मुझे निरंतरता के लिए पुराने कोड से मेल खाने की कोशिश करनी चाहिए? क्या पुराने प्रारूप को सही ठहराने के लिए इस मामले में पर्याप्तता है?

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



@ शविक - बाह। जब तक आप प्रतिबिंब में टाइप कर रहे हैं तब तक कोई अंतर नहीं है। यदि आप सेवा या लाइब्रेरी इंटरफ़ेस के रूप में पारंपरिक रूप से उजागर कर रहे हैं, तो आप एक ऐसे इंटरफ़ेस को उजागर करने जा रहे हैं जिसके लिए किसी भी संपत्ति की आवश्यकता है। ओपी उन चीजों में से कोई भी नहीं कर रहा है।
तेलस्टिन

2
इन सीमित मामलों में कोई तकनीकी कारण नहीं है । डीबगर, क्लास डायग्राम, इंटलिसेंस में गुणों को अलग तरह से न भूलें और जब आपको लगता है कि आप प्रतिबिंब नहीं कर रहे हैं, तो .NET फ्रेमवर्क है। WinForms, WPF, और कई अन्य घटक आंतरिक रूप से प्रतिबिंब का उपयोग करते हैं और वे अलग-अलग गुणों का इलाज करते हैं, इसलिए सार्वजनिक क्षेत्रों का उपयोग करने की सलाह, इस साइट पर बहुत सारे देवों द्वारा खराब रूप से प्राप्त की जाएगी।
केविन मैककॉर्मिक

1
@KevinMcCormick और फ्रेमवर्क खेतों के साथ पूरी तरह से अच्छा व्यवहार करता है (जो मैं समझता हूं) से। यह वास्तव में कोई बात नहीं है क्योंकि अब ऑटो-गुण हैं, लेकिन बड़ी समस्या चीजों को पहले स्थान पर सार्वजनिक कर रही है। बहुत दूर, बहुत से लोग सोचते हैं कि बस चीजों को गुण बनाने से किसी भी तरह उन्हें 'सार्वजनिक क्षेत्र नहीं बनाते हैं'।
तेलेस्टिन

2
फ्रेमवर्क उन्हें अलग तरीके से संभालता है: EF POCO में एक सार्वजनिक क्षेत्र का उपयोग करने का प्रयास करें, इसे DataGridView में बाँधें, प्रॉपर्टीग्रिड का उपयोग करें, आदि। मैंने अभी-अभी अपने डिकम्पाइलर में एक त्वरित खोज की। Type.GetProperties / Getperperty और फ्रेमवर्क इस विधि के लिए कॉल करता है। सैकड़ों बार, लेकिन GetField के लिए नहीं। निचला रेखा, वे अलग-अलग हैं, और सार्वजनिक डेटा के लिए गुणों का हमेशा उपयोग करने की सिफारिश आंशिक रूप से इस तथ्य पर आधारित है। यह कभी भी खेतों का उपयोग नहीं करता है, लेकिन उस मामले को औचित्य की आवश्यकता है। हालाँकि, आपका अन्य बिंदु निश्चित रूप से सही है, सार्वजनिक डेटा को लापरवाही से उजागर करना हमेशा एक बुरा विचार है।
केविन मैककॉर्मिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.