2010-09-16 8 views
27

मुझे यकीन है कि मैंने कहीं देखा है कि मैं अपनी इनिट() विधि के ऊपर एक विशेषता का उपयोग कर निम्न कार्य कर सकता हूं, जो संकलक को बताता है कि Init() विधि को केवल निर्माता से ही बुलाया जाना चाहिए, इस प्रकार केवल पढ़ने की अनुमति सेट करने के लिए फ़ील्ड। मैं भूल गया कि विशेषता क्या कहलाती है, और मुझे इसे Google पर नहीं लग रहा है।मैं एक प्रारंभिक विधि में एक पाठक फ़ील्ड कैसे सेट करूं जिसे कन्स्ट्रक्टर से बुलाया जाता है?

public class Class 
{ 
    private readonly int readonlyField; 

    public Class() 
    { 
     Init(); 
    } 

    // Attribute here that tells the compiler that this method must be called only from a constructor 
    private void Init() 
    { 
     readonlyField = 1; 
    } 
} 

उत्तर

33

Rob's answer मेरी पुस्तक में ऐसा करने का तरीका है। आप out मानकों का प्रयोग करके यह कर सकते हैं आप एक से अधिक क्षेत्रों प्रारंभ करने की जरूरत है:

public class Class 
{ 
    private readonly int readonlyField1; 
    private readonly int readonlyField2; 

    public Class() 
    { 
     Init(out readonlyField1, out readonlyField2); 
    } 

    protected virtual void Init(out int field1, out int field2) 
    { 
     field1 = 1; 
     field2 = 2; 
    } 
} 

व्यक्तिगत तौर पर मैं इस तरह के जब आप अपने क्षेत्रों readonly होना चाहते हैं के रूप में कुछ परिदृश्यों, में समझ में आता है लगता है, लेकिन आप भी होना चाहता हूँ एक व्युत्पन्न वर्ग में उन्हें अलग-अलग सेट करने में सक्षम (कुछ protected कन्स्ट्रक्टर के माध्यम से पैरामीटर का एक टन श्रृंखला के बिना)। लेकिन शायद यह सिर्फ मुझे है।

+2

पैरामीटर बाहर, युक! –

+1

@Chuck: अरे, मैंने कभी नहीं कहा कि यह सुंदर था। –

+0

मैंने इसे प्रतिबिंब का उपयोग करके हल किया। नीचे देखें .. – Derar

6

यह नहीं किया जा सकता है। फील्ड्स जो readonly के साथ टैग कर रहे हैं केवल निर्माता

+0

यह नहीं कि यह पूरी तरह से गलत है, लेकिन यह उत्तर वास्तव में यहां के अन्य उत्तरों की तुलना में पीला करता है। एक वाक्य "नहीं किया जा सकता" एक वाक्य का उत्तर वांछित होने के लिए बहुत कुछ छोड़ देता है। शायद यह पहले जवाबों में से एक था हालांकि? – Assimilater

1

सी # संकलक केवल अगर तुम उन्हें इनलाइन आरंभ कर रहे हैं आप केवल पढ़ने के लिए फ़ील्ड सेट करने देता है से सेट किया जा सकता:

private readonly int readonlyField = 1; 

या निर्माता से:

public Class() 
{ 
    readonlyField = 1; 
} 
9

एकमात्र समाधान मैं के बारे में सोच सकते हैं Init() विधि है कि readonly क्षेत्र असाइन किया जाना आवश्यक से मान देने के लिए है:

public class Class 
{ 
    private readonly int readonlyField; 

    public Class() 
    { 
     readonlyField = Init(); 
    } 

    private int Init() 
    { 
     return 1; 
    } 
} 
+0

मुझे यकीन था कि मैंने यह देखा .. मेरा दिमाग मुझ पर चाल चलाना चाहिए। धन्यवाद सभी –

+0

@ बेन एंडरसन, मुझे पता है कि आपका क्या मतलब है - मैंने कुछ दिन पहले नेट को घुमाया था, क्योंकि मुझे यकीन था कि मैं कहीं पढ़ूंगा कि एसएमबी 2 एक रिमोट सर्वर से दूसरी फाइल में कॉपी-कॉपी करने की अनुमति देता है अनुरोध करने के लिए ग्राहक मशीन के माध्यम से। घंटे गुम हो गए और मुझे कोई सबूत नहीं मिला, हालांकि मैं * अशिष्ट था * मैं पढ़ता था कि यह संभव था! : एस – Rob

14

नहीं, आप नहीं कर सकते। असल में आपको कन्स्ट्रक्टर में प्रारंभिक प्रदर्शन करना चाहिए - यही वह है जो इसके लिए है।

पुन: उपयोग के प्रयोजनों के लिए, यदि आपके पास एकाधिक रचनाकार हैं, तो उनमें से एक को "मास्टर" कन्स्ट्रक्टर में श्रृंखला बनाने के लिए सभी वास्तविक कार्य करने की कोशिश करें।

मूल्यों के किसी भी जटिल गणना की आवश्यकता है, तो यह उपयुक्त नहीं हो सकता निर्माता में वैसे भी गणना की जा करने के लिए - और अगर ऐसा है, तो आप जो रिटर्न मूल्य के लिए एक निजी विधि में गणना हिस्सा रख सकते हैं, तो उस विधि को कन्स्ट्रक्टर से कॉल करें।

संपादित करें: मैं इसे करने का वास्तविक तरीका के रूप में प्रतिबिंब शामिल नहीं करूंगा। ऐसे सभी प्रकार के बयान हैं जो आप कर सकते हैं जिसमें प्रतिबिंब के माध्यम से दुरुपयोग शामिल नहीं है। स्ट्रिंग अक्षर "x" को "y" में बदलना चाहते हैं? निश्चित रूप से, यदि आप सही अनुमतियां हैं, तो आप प्रतिबिंब के साथ ऐसा कर सकते हैं ... लेकिन आपको बिल्कुल नहीं करना चाहिए।

+0

हल किया जा सकता है। उदाहरण के नीचे देखें। – Derar

4

जेरेड सही है; यह नहीं हो सकता। जिन कामकाजों के बारे में मैं सोच सकता हूं वे हैं:

  1. घोषणा में फ़ील्ड आरंभ करें।
  2. कन्स्ट्रक्टर में फ़ील्ड आरंभ करें (मैन्युअल रूप से अपनी Init विधि इनलाइन करें)।
  3. एक मूल्य के लिए एक विधि द्वारा दिया, उदा .: _myField = GetInitialMyFieldValue();
  4. के क्षेत्र असाइन करें, Init विधि के क्षेत्र दर्रा out संशोधक के साथ।यह उपयोगी हो सकता है यदि आपके पास प्रारंभ करने के लिए कई फ़ील्ड हैं, जो कि कन्स्ट्रक्टर पैरामीटर पर निर्भर हैं। जैसे

private readonly int _x; 
private readonly string _y; 

private void Init(int someConstructorParam, out int x, out string y){ .. } 

public Class(int someConstructorParam) 
{ 
    Init(someConstructorParam, out _x, out _y); 
} 
0

मैं यह काम करता है, तो उपयोग प्रतिबिंब लगता है। वास्तव में यह मेरे लिए काम करता है:

public class Class 
     { 
      private readonly int readonlyField; 
     public int MyField() 
     { 
      return readonlyField; 
     } 
     public Class() 
     { 
      readonlyField = 9; 
     } 
    } 

और

static void Main(string[] args) 
     { 

      Class classObj = new Class(); 
      Console.WriteLine(classObj.MyField());//9 

      Misc.SetVariableyByName(classObj, "readonlyField", 20);//20 
      Console.WriteLine(classObj.MyField()); 
     } 

इस SetVariableByName() है:

public static b 

ool SetVariableyByName(object obj, string var_name, object value) 
      { 
       FieldInfo info = obj.GetType().GetField(var_name, BindingFlags.NonPublic| BindingFlags.Instance); 
       if (info == null) 
       return false; 
      /* ELSE */ 
      info.SetValue(obj, value); 
      return true;   
     } 

केवल बात यह है कि readonlyField सार्वजनिक निजी नहीं है। मुझे पता है कि आप एक निजी क्षेत्र को संपादित कर सकते हैं, लेकिन मुझे यकीन नहीं है कि यह मेरे लिए क्यों काम नहीं कर रहा है!

+0

अब निजी सदस्य चर पर काम करता है .. – Derar

+10

सिर्फ इसलिए कि आप * ऐसा कर सकते हैं इसका मतलब यह नहीं है कि आपको * चाहिए * ... और निश्चित रूप से कई परिस्थितियों में आपको ऐसा करने की अनुमति नहीं होगी। –

+0

मुझे नहीं लगता कि यह प्रतिबिंब का मतलब क्या था। अनावश्यक प्रदर्शन हिट ... – clyc

12

प्रारंभिक विधि का उपयोग करने के बजाय, अपने सभी अन्य रचनाकारों के माध्यम से मूल निर्माता को विरासत में लाने के बारे में कैसे। अर्थात

public class MyClass 
{ 
    readonly int field1; 
    readonly double field2; 
    public MyClass(int field1, double field2) 
    { 
     //put whatever initialization logic you need here... 
     field1 = 10; 
     field2 = 30.2; 
    } 
    public MyClass(int field1, double field2p1, double field2p2) 
     : this(field1, (field2p1 + field2p2)) 
    { 
     //put anything extra in here 
    } 
} 

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

+0

यह निश्चित रूप से रचनाकारों के बीच कोड साझा करने का एक शानदार तरीका है। – MikeMurko

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

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