2010-08-23 13 views
19

क्या किसी ऑब्जेक्ट के रीडोनली इंस्टेंस को वापस करने का कोई तरीका है?सी # रीडोनली ऑब्जेक्ट

public class Person 
{ 
    public String FirstName { get; set; } 
    public String LastName { get; set; } 
} 

public class SomeClass 
{ 
    public SomeClass(Person manager) 
    { 
     if (manager == null) 
      throw new ArgumentNullException("manager"); 

     _manager = manager; 
    } 

    private readonly Person _manager; 
    public Person Manager 
    { 
     get { return _manager; } //How do I make it readonly period! 
    } 
} 

एक क्लोन() लौट रहे ताकि किसी भी परिवर्तन और क्लोन करने के लिए किया नहीं कर रहे हैं मूल से यह करने के लिए एक ही रास्ता है? मैं Arrays के लिए जानता हूँ वहाँ केवल पढ़ने के रूप में ऐरे वापस करने के लिए एक समारोह है। ओह, और मुझे पता है कि यह एक संदर्भ प्रकार है ... मैं सोच रहा हूं कि लेखन भाग को लॉक करने के लिए कुछ छुपा सी # सुविधा है या नहीं।

मैं जेनेरिक रीडऑनली रैपर क्लास के साथ आने की कोशिश कर रहा था, लेकिन कुछ महंगे प्रतिबिंब और इस तरह के बिना गुणों को आसानी से प्राप्त करने के तरीके को समझ नहीं पाया।

ओह, और मैं वास्तव में कक्षा के दूसरे संस्करण को बनाने से बचने की कोशिश कर रहा हूं जो सभी पाठक गुण हैं। उस समय, मैं क्लोन वापस भी कर सकता हूं।

+1

टिप्पणियों के आधार पर: बूलियन (IsReadOnly) अपडेट रोकने के लिए उचित तरीके से किया जाता है वहाँ किसी भी ज्ञात "ReadOnly" सामान्य आवरण वर्ग तेज है कि है और कुशल? जिसने मुझे बनाने की कोशिश की थी वह प्रतिबिंब का उपयोग करना था, जो वास्तव में मैं नहीं करना चाहता हूं अगर मैं इससे बच सकूं। –

उत्तर

33

एक अतिरिक्त कक्षा बनाने से खुद को बचाने के लिए, आप इसे एक इंटरफ़ेस आईपर्सन के रूप में कार्यान्वित कर सकते हैं जिसने केवल गुणों को पढ़ा है।

public interface IPerson 
{ 
    string FirstName { get; } 
    string LastName { get; } 
} 
public class Person:IPerson 
{ 
    public String FirstName { get; set; } 
    public String LastName { get; set; } 
} 

public class SomeClass 
{ 
public SomeClass(Person manager) 
{ 
    if (manager == null) 
     throw new ArgumentNullException("manager"); 

    _manager = manager; 
} 

private readonly Person _manager; 
public IPerson Manager 
{ 
    get { return _manager; } //How do I make it readonly period! 
} 
} 
+1

+1, समस्या का समाधान। –

+1

कंक्रीट प्रकारों के बजाय इंटरफेस का उपयोग करने के बहुत अच्छे कारण हैं (और यदि 'व्यक्ति के पास कोई व्यवहार है, तो मैं भी इसकी अनुशंसा करता हूं) ... लेकिन यह कक्षा बनाने के विरुद्ध किसी भी प्रयास को कैसे बचाता है? –

+5

मुझे यह भी पसंद है, लेकिन क्या उनके लिए इसे किसी व्यक्ति वर्ग में वापस डालना आसान नहीं होगा? 'व्यक्ति iCanChangeProperties = (व्यक्ति) SomeClass.Manager;' और कास्ट गुणों में परिवर्तन करने के लिए उस संदर्भ का उपयोग करके उनके खिलाफ सुरक्षा नहीं करता है ... मुझे सिर्फ क्लोन के साथ रहना पड़ सकता है। हालांकि, केवल पढ़ने वाला इंटरफ़ेस अच्छा होगा, इसलिए प्रतिबिंब उन्हें बताता है कि वे ** ** सेटर गुण नहीं कर सकते हैं। –

2

ऐसी कोई सुविधा नहीं है - आपने अपने विकल्पों को कवर किया है।

या तो इसे क्लोन करें या केवल पढ़ने के लिए Person प्रकार बनाएं। बाद वाला दृष्टिकोण आमतौर पर पसंद किया जाता है क्योंकि अर्थशास्त्र स्पष्ट होते हैं: यह कॉलर्स के लिए स्पष्ट है कि उन्हें उदाहरण को संशोधित नहीं करना चाहिए (और नहीं)।

+0

यह दृष्टिकोण सी # मानक पुस्तकालय में भी काफी आम है। 'स्ट्रिंग'/'स्ट्रिंगबिल्डर 'और' उरी '/' उरीबिल्डर 'जैसी चीजें देखें। यह केवल तभी समझ में आता है जब केवल पढ़ने के लिए उपयोग बहुत अधिक है, जो उन दोनों के लिए मामला है। – Ekevoo

0

नहीं। आप सी ++ - शैली const -ness जैसे कुछ ढूंढ रहे हैं, और variousreasons सी # के पास ऐसा नहीं है।

हालांकि, अज्ञात प्रकार वास्तव में अपरिवर्तनीय हैं।

1

कक्षा से बाहरी रूप से आपके ऑब्जेक्ट के सभी गुणों को पढ़ने के लिए कोई तरीका नहीं है। उपरोक्त आपके उदाहरण में, आप _manager गुणों को केवल पढ़ने के लिए नहीं बना सकते हैं, जब तक कि आप व्यक्ति वर्ग के भीतर गुणों को केवल पढ़ने के लिए नहीं बदल देते।

आप व्यक्ति वर्ग आंतरिक के गुणों का सेटटर बना सकते हैं, जिसका अर्थ है कि एक ही असेंबली के भीतर केवल वर्ग ही व्यक्ति संपत्तियों को बदल सकता है।

या, यदि आप गुणों का निजी सेटर बनाते हैं, तो केवल व्यक्ति के भीतर कोड गुणों के मूल्यों को बदल सकता है।

4

आप वस्तु रोक सकते हैं Castle.DynamicProxy की मदद से कुछ परिस्थितियों में (यह अपरिवर्तनीय बनाना)। विवरण के लिए इस ब्लॉग को post पढ़ें।

5

आप .., अपरिवर्तनीय वस्तु में व्यक्ति वर्ग बदल सकता है नीचे के रूप में

public class Person 
{ 
    public Person(string firstName, string lastName) 
    { 
     FirstName = firstName; 
     LastName = lastName; 
    } 

    public String FirstName { get; private set; } 
    public String LastName { get; private set; } 

} 
0

बेनामी वस्तुओं केवल पढ़ने के लिए कर रहे हैं।

1

यहां एक अन्य उदाहरण है, कैसे सूचीबद्ध है। List.AsReadOnly .NET Framework 2.0 में लागू किया गया है।

public class Person 
{ 
    private string _firstName; 
    public string FirstName 
    { 
     get { return _firstName; } 
     set 
     { 
      if (!IsReadOnly) _firstName = value; 
      else throw new AccessViolationException("Object is read-only."); 
     } 
    } 

    private string _lastName; 
    public string LastName 
    { 
     get { return _lastName; } 
     set 
     { 
      if (!IsReadOnly) _lastName = value; 
      else throw new AccessViolationException("Object is read-only."); 
     } 
    } 

    internal virtual bool IsReadOnly { get { return false; } } 

    public ReadOnlyPerson AsReadOnly() 
    { 
     return new ReadOnlyPerson(this); 
    } 

    public class ReadOnlyPerson : Person 
    { 
     private Person _person; 
     internal override bool IsReadOnly { get { return true; } } 

     internal ReadOnlyPerson(Person person) // Contructor 
     { 
      this._person = person; 
     } 
    } 
} 

यह परीक्षण करने के लिए:

static void Main(string[] args) 
{ 
    Person p1 = new Person(); 
    p1.FirstName = "Joe"; 
    p1.LastName = "Bloe"; 
    Console.WriteLine("First = {0} Last = {1}", p.FirstName, p.LastName); 

    var p2 = p1.AsReadOnly(); 
    p2.FirstName = "Josephine"; // AccessViolationException 
} 
संबंधित मुद्दे