2012-03-02 11 views
13

मेरे प्रबंधक ने मुझसे पूछा है कि एक सेटटर के साथ संपत्ति का उपयोग करना अच्छा अभ्यास है, लेकिन कोई गेटर नहीं है।क्या कोई संपत्ति नहीं है जिसके पास कोई गेटटर नहीं है?

public class PropertyWrapper 
{ 
    private MyClass _field; 

    public MyClass Property 
    { 
     set { _field = value; } 
    } 

    public string FirstProperty 
    { 
     get { return _field.FirstProperty; } 
    } 

    public string SecondProperty 
    { 
     get { return _field.SecondProperty; } 
    } 
} 

वह अन्य संपत्तियों का उपयोग करेंगे एक निजी क्षेत्र, इस सेटर द्वारा निर्धारित से गुण का पर्दाफाश करने के।

मेरा सुझाव केवल एक निजी क्षेत्र का उपयोग करना था और इसे कन्स्ट्रक्टर में सेट करना था, जो इस परिदृश्य में ठीक काम करता है। अगर मुझे पहले एक निर्मित ऑब्जेक्ट की आवश्यकता होती है (शायद पॉलिमॉर्फिज्म का उपयोग भी) तो मैं अभी भी गेटटर-कम संपत्ति के बजाय Load विधि पसंद करूंगा।

लेकिन मुझे रूचि है। हम दोनों सर्वोत्तम प्रथाओं से बहुत चिंतित हैं और यह सुनिश्चित करने का प्रयास करते हैं कि हमारा कोड स्टैंडराइज्ड है। क्या किसी के पास गेट-कम गुणों के बारे में कोई आधिकारिक लेख है? या बेहतर अभी भी - इस उपयोग का एक उदाहरण .NET Framework में ही है?

+2

इसके साथ स्वाभाविक गलत कुछ भी नहीं है, लेकिन यह असामान्य है। इसके लिए एक संपत्ति क्यों है यदि आप इसे केवल सेट कर सकते हैं? – Oded

+3

देखें http://stackoverflow.com/questions/4695551/write-only-properties-whats-the-point – kaj

+0

@KAJ धन्यवाद! मुझे पहले मेरी खोज में वह नहीं मिला। – Connell

उत्तर

16

आधिकारिक लेख: Design Guidelines for Developing Class Libraries -> Member Design Guidelines -> Property Design

-केवल सेट गुण प्रदान करते हैं।

यदि संपत्ति प्राप्तकर्ता प्रदान नहीं किया जा सकता है, तो इसके बजाय कार्यक्षमता लागू करने के लिए एक विधि का उपयोग करें। विधि का नाम सेट के साथ शुरू होना चाहिए जिसके बाद संपत्ति का नाम क्या होगा। उदाहरण के लिए, AppDomain बजाय एक सेट केवल संपत्ति CachePath बुलाया होने की एक विधि कहा जाता SetCachePath है।

2

गेटटर-कम संपत्ति होने के साथ कुछ भी गलत नहीं है, यदि यह आपके कोड को सबसे समझने योग्य और रखरखाव योग्य बनाता है। हालांकि, इसके लिए अच्छे मामले शायद दुर्लभ हैं।

सबसे अच्छी चीज जो मैंने कभी भी उपयोग की है, गेटटर-कम गुण यूनिट परीक्षण कक्षाओं के लिए है जिनके गुणों में पहुंचने योग्य सेटर्स हैं। उदाहरण के लिए:

public class MyClass 
{ 
    public int MyId { get; protected set; } 
} 

public class MyClass_Test : MyClass 
{ 
    public int MyId_Set 
    { 
     set { MyId = value; } 
    } 
} 

इस तरह से मैं इकाई परीक्षण में एक MyClass_Test उपयोग कर सकते हैं और इकाई परीक्षण करने की क्षमता के लिए एक विशेष विधि के साथ MyId के लिए एक मूल्य पूर्व निर्धारित।

इसके अलावा, आपके उदाहरण के लिए सीधी प्रतिक्रिया, का उपयोग कर एक private get शायद यह चारों ओर बेहतर तरीका होगा में: यदि आप ऐसा नहीं कर सकते हैं लेकिन यह थोड़ा अजीब प्रतीत होता है कहने के लिए

public class PropertyWrapper 
{  
    public MyClass Property { private get; set; } 

    public string FirstProperty 
    { 
     get { return Property.FirstProperty; } 
    } 

    public string SecondProperty 
    { 
     get { return Property.SecondProperty; } 
    } 
} 
+1

यूनिट परीक्षण के लिए कक्षा में कुछ क्षमताओं को जोड़ना एक कोड गंध प्रतीत होता है। –

+0

मुझे लगता है मैं निर्दिष्ट कर सकते हैं '_Test' वर्ग केवल इकाई परीक्षण के संदर्भ में मौजूद है - यह मेरे सेटअप करने के लिए वस्तु की स्थिति की अनुमति देता है और एक इकाई के रूप में अलग-अलग तरीकों का परीक्षण। – eouw0o83hf

+0

मैं 'MyClass.MyId' संरक्षित के सेटटर बनाने के बारे में बात कर रहा हूं। यदि यह केवल यूनिट परीक्षण के लिए उपयोग किया जा रहा है - यह आईएमएचओ एक अच्छा डिजाइन नहीं है। –

0

थेर के लिए कुछ भी नहीं। मेरे पास एक निजी संपत्ति और एक विधि होगी जो इसे सेट करेगी i.e.

private string _test; 

public void SetTest(string test) 
{ 
_test = test; 
} 
0

आपको याद रखना होगा कि गुण क्यों मौजूद हैं। वे निम्नलिखित पैटर्न

class Foo 
{ 
    private Bar _bar; 

    public Bar GetBar() 
    { 
     return _bar; 
    } 

    public void SetBar(Bar bar) 
    { 
     _bar = bar; 
    } 
} 

की जगह जबकि एक संपत्ति नहीं सेटर के साथ मेरे लिए अजीब लग रहा है, मुझे नहीं लगता कि कोई प्राप्त विधि के साथ एक सेट विधि होने बिल्कुल अजीब लग रहा है।

असल में, मुझे पूरा यकीन है कि गुण वाक्य रचनात्मक चीनी हैं और प्राप्त/सेट विधियों के रूप में पुनः लिखे गए हैं। या कम से कम वास्तव में बंद करो।

+0

मैं एक ही राय का हूँ। 'गेटबार' के बिना 'सेटबार' सामान्य प्रतीत होता है, लेकिन संकलक एक सी # संपत्ति को वैसे भी करता है! – Connell

3

मेरे पास कोई आधिकारिक लेख या उदाहरण नहीं हैं .. केवल राय।

और मेरी राय में एक ऐसी संपत्ति जिसे पढ़ा नहीं जा सकता वह एक जानवर है जो क्रोध और भ्रमित होगा।

यह इरादे से नीचे आता है। एक संपत्ति कहती है, "मैं उपभोक्ता को मुझे पढ़ने की अनुमति देना चाहता हूं, और संभवतः मुझे भी लिख सकता हूं"। "SetSomeAttribute" जैसे कुछ नाम का एक फ़ंक्शन केवल लिखने का इरादा घोषित करता है।

पूरा भी है, मेरा डेटा है तो मैं इसे वापस क्यों नहीं पढ़ सकता।

तो मेरी राय में, केवल एक लिखने वाली संपत्ति का उपयोग करने का कोई अच्छा कारण नहीं है।

+0

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

+0

@ सर्वी: मुझे यकीन नहीं है कि मैं अनुसरण करता हूं। यदि कोई संपत्ति केवल लिखने योग्य है, तो कोई भी नहीं, उस वर्ग/संरचना का एक और उदाहरण भी संपत्ति को पढ़ सकता है। तो यह तुलना कैसे होगी? इस उदाहरण में मैं केवल लिखने वाली संपत्ति के बजाय एक .SetPassword() विधि का चयन करता हूं, और जनता की तुलना करता हूं .शॉप गुण। –

+0

ठीक है, सेटर में कोड को स्पष्ट रूप से इसे कुछ निजी स्टोरेज माध्यम में स्टोर करने की आवश्यकता होगी ताकि कक्षा आंतरिक रूप से इसका उपयोग कर सके; और कोई गेटटर के साथ स्वत: जेनरेट की गई संपत्ति स्पष्ट रूप से व्यर्थ है (और संकलक द्वारा भी हटाया जा सकता है)। यह मूल रूप से सेटपैसवर्ड विधि होने जैसा ही होगा, मैं सहमत हूं। मैं यह नहीं कह रहा हूं कि यह बेहतर होगा, केवल यह एक दुर्लभ मामला है जहां मैंने टीम के सदस्य को लागू करने के लिए इसका विरोध नहीं किया। – Servy

8

प्रश्नों को ध्यान में रखते हुए हैं: क्या किसी के पास गेटर-कम संपत्तियों के बारे में कोई आधिकारिक लेख है? या बेहतर अभी भी - इस उपयोग का एक उदाहरण .NET Framework में ही है? और राय के बारे में नहीं; मैं एक त्वरित परीक्षण आवेदन विधानसभाओं एक डिफ़ॉल्ट सांत्वना आवेदन में लोड के सभी प्रकार के सभी के गुणों के सभी के माध्यम से पढ़ने के लिए लिखा है:

foreach (var assem in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    foreach (var type in assem.GetTypes()) 
    { 
     foreach (var prop in type.GetProperties()) 
     { 
      if (!prop.CanRead) 
       Console.WriteLine("Assembly: {0}; Type: {1}; Property: {2}", assem.FullName, type.Name, prop.Name); 
     } 
    } 
} 

परिणाम हैं:

विधानसभा: mscorlib , संस्करण = 4.0.0.0, संस्कृति = तटस्थ, PublicKeyToken = b77a5c561934e089; टाइप करें: FileIOAccess; संपत्ति: PathDiscovery

असेंबली: mscorlib, संस्करण = 4.0.0.0, संस्कृति = तटस्थ, PublicKeyToken = b77a5c561934e089; टाइप करें: रीडायरेक्शनप्रॉक्सी; संपत्ति: ऑब्जेक्टमोड

तो ऐसा लगता है कि ढांचा इसे कम से कम उपयोग करता है। मैं ऐसा करने का सुझाव दूंगा।

संपादित

दिलचस्प बात यह डिबगर संलग्न पैदावार कई और अधिक परिणामों के साथ एक ही कोड चलाने:

Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: FileIOAccess; Property: PathDiscovery 
Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: RedirectionProxy; Property: ObjectMode 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: AxHost; Property: Site 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DataGridTextBoxColumn; Property: PropertyDescriptor 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: FirstDisplayedFrozenCol 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: FirstDisplayedFrozenRow 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: LastDisplayedFrozenCol 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: LastDisplayedFrozenRow 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: LastDisplayedScrollingRow 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ErrorProvider; Property: Site 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: WebBrowserBase; Property: Site 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: WebBrowser; Property: Site 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DropDownButton; Property: UseComboBoxTheme 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridErrorDlg; Property: Details 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridErrorDlg; Property: Message 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DropDownHolder; Property: ResizeUp 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridViewEdit; Property: DontFocus 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridViewEdit; Property: DisableMouseHook 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: MouseHook; Property: DisableMouseHook 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ManifestSignedXml; Property: Resolver 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ContainerProxy; Property: Bounds 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: RightToLeftProxy; Property: Bounds 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: TopDownProxy; Property: Bounds 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: BottomUpProxy; Property: Bounds 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ElementProxy; Property: Bounds 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: VerticalElementProxy; Property: Bounds 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: IconComparer; Property: SortOrder 
Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: MultiPropertyDescriptorGridEntry; Property: PropertyValue 
Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlDocument; Property: XmlResolver 
Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlDocument; Property: InnerText 
Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ProcessThread; Property: IdealProcessor 
Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ProcessThread; Property: ProcessorAffinity 
Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlAttribute; Property: InnerText 
Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlAttribute; Property: InnerXml 
Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: AnonymousPipeServerStream; Property: ReadMode 
Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: AnonymousPipeClientStream; Property: ReadMode 
Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ManifestSignedXml; Property: Resolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlResolver; Property: Credentials 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlNullResolver; Property: Credentials 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlSecureResolver; Property: Credentials 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUrlResolver; Property: Credentials 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUrlResolver; Property: Proxy 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUrlResolver; Property: CachePolicy 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlReaderSettings; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlTextReader; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlValidatingReader; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DocumentXmlWriter; Property: NamespaceManager 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DocumentXmlWriter; Property: Navigator 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DocumentXmlWriter; Property: EndNode 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlAttribute; Property: InnerText 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlAttribute; Property: InnerXml 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlDocument; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlDocument; Property: InnerText 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUnspecifiedAttribute; Property: InnerText 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUnspecifiedAttribute; Property: InnerXml 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlPreloadedResolver; Property: Credentials 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XslTransform; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlSchemaSet; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlSchemaValidator; Property: XmlResolver 
Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XsdValidator; Property: Context 
+0

शानदार जवाब! मैंने स्वयं यह कोड चलाया और उसी परिणाम भी थे। मैंने भी अपना प्रबंधक दिखाया;) धन्यवाद! – Connell

+0

ये परिणाम इंगित नहीं करते हैं कि संपत्ति सार्वजनिक रूप से सुलभ है या नहीं - जो एक दिलचस्प मीट्रिक हो सकती है। –

+0

सिर्फ इसलिए कि एमएस करता है इसका मतलब यह नहीं है कि यह एक अच्छा अभ्यास है। –

-3

आप गुण है कि tidier हैं, और जिस पर आपका पूर्ण अभिगम नियंत्रण व्यायाम कर सकते हैं हो सकता है, गंदे _localVariable, और संपत्ति वाक्यविन्यास के बिना।

उदाहरण:

/// <summary> 
    /// Publicly readable, privately settable. 
    /// </summary> 
    public int FirstProperty { get; private set; } 

    /// <summary> 
    /// Entirely private 
    /// </summary> 
    private int SecondProperty { get; set; } 
+1

-1: असंबंधित उत्तर - प्रश्न "उपयोगी होने के बिना संपत्ति" थी और जवाब "कैसे प्राप्त करें" देखें। –

0

वे संभवतः निर्भरता इंजेक्शन के लिए इस्तेमाल किया जा सकता है जब किसी कारण से न तो निर्माता और न ही विधि इंजेक्शन आप के लिए काम करता है।

लेकिन मैं इस तरह के मामले की कल्पना नहीं कर सकता।

0

खैर, वे वस्तु initializers में निजी क्षेत्रों के लिए अच्छा उपयोग हो सकता है:

var obj = new MyClass 
{ 
    Prop1 = value1, 
    Prop2 = value2 
}; 

जो एक वैकल्पिक तरीका सिर्फ निर्माता पैरामीटर के रूप में उन्हें लिखने के लिए हो सकता है:

var obj = new MyClass(value1, value2); 

लेकिन अगर देखते हैं कई (वैकल्पिक) पैरामीटर, लिखित रूप से गुण आसान हो सकते हैं।

0

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

  1. एक अलग विधि को परिभाषित करें जो एक पैरामीटर स्वीकार करता है।
  2. एक गेटटर परिभाषित करें जो हमेशा एक ही मान (उदा। शून्य) देता है। चाहे यह समझ में आता है या आश्चर्य संदर्भ पर निर्भर करता है।
संबंधित मुद्दे