2009-10-30 15 views
25

को भेजने से पहले शीर्षक थोड़ा अस्पष्ट हो सकता है, लेकिन मैं शब्द इस लिए एक बेहतर तरीका के बारे में सोच नहीं सकता था।संशोधित करना पैरामीटर मान बेस निर्माता

मुझे लगता है कि मैं एक आधार निर्माता बुला से पहले एक व्युत्पन्न निर्माता फोन नहीं कर सकते हैं, लेकिन मैं उन्हें किसी भी तरह आधार पर गुजर करने से पहले संशोधित कर सकते हैं/बनाने पैरामीटर मान?

उदाहरण के लिए

,

public enum InputType 
{ 
    Number = 1, 
    String = 2, 
    Date = 3 
} 

public class BaseClass 
{ 
    public BaseClass(InputType t) 
    { 
     // Logic 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public DerivedClass(int i) 
     : base(value) 
    // Can I do something to infer what value should be here? 
    { 
     // Logic 
    } 
} 

अगर मैं एक व्युत्पन्न वर्ग कि आधार निर्माता के लिए आवश्यक मूल्य का अनुमान लगा सकते है (इस उदाहरण में, InputType.Number एक int के लिए मान्य होगा,) वहाँ संशोधित करने के लिए एक रास्ता है और/या व्युत्पन्न कन्स्ट्रक्टर निष्पादन से पहले आधार कन्स्ट्रक्टर को पास किए गए मान बनाएं?

उत्तर

37

मैं तुम्हें आधार वर्ग निर्माता के पैरामीटर सूची में स्थिर तरीकों कह सकते हैं उम्मीद है।

public class DerivedClass : BaseClass 
{ 
    public DerivedClass(int i) 
     : base(ChooseInputType(i)) 
    { 
    } 

    private static InputType ChooseInputType(int i) 
    { 
     // Logic 
     return InputType.Number; 
    } 
} 
2

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

public DerivedClass(int i) 
    : base((InputType)i) 
{ 
} 
+0

आप DerivedClass निर्माता में तर्क के माध्यम से "मान" नहीं बना सकते हैं, हालांकि, आधार (...) पहले चलाया जाता है। –

+0

@ रेड, हाँ, जो एक टाइपो था। रखने के लिए (इनपुट टाइप) i। फिक्स्ड – JaredPar

+0

हां, आप कास्ट कर सकते हैं। लेकिन वह मूल्य बनाने के लिए तर्क का उपयोग करने का एक तरीका मांग रहा था, जिसे आप नहीं कर सकते। –

0

सं

के लिए आधार निर्माता DerivedClass निर्माता में किसी भी तर्क से पहले चलाया जाता है, इसलिए वहाँ तर्क इंजेक्षन करने के लिए कोई रास्ता नहीं है।

हालांकि, आप आधार वर्ग निर्माता, चला सकते हैं तो आदेश मान बदलने के लिए dervied वर्ग के निर्माता के दौरान आधार वर्ग में गुण सेट करें।

0

आप कहते हैं कि

मुझे लगता है कि मैं एक आधार निर्माता

लेकिन तब आप इस कोड को दिखाने बुला से पहले एक व्युत्पन्न निर्माता कॉल नहीं कर सकते

public DerivedClass(int i) 
    : base(value) 
{ 
    // Is it possible to set "value" here? 
    // Logic 
} 

जब कि कोड ब्लॉक दर्ज किया गया है आप बेस क्लास कन्स्ट्रक्टर पहले ही चल चुके हैं। हालांकि आप बेस कन्स्ट्रक्टर (कुछ स्पष्ट बाधाओं के साथ) को पास करने से पहले अभिव्यक्ति में मान को संशोधित कर सकते हैं। हालांकि, आपके पास 'मान' तक पहुंच नहीं होगी जबतक कि यह कन्स्ट्रक्टर में इनपुट न हो।

+0

संपादित देखें, मैंने गलत रेखा पर टिप्पणी टाइप की है .. इसे बेस कन्स्ट्रक्टर कॉल के नीचे टाइप करने का मतलब है। –

+0

ठीक है, मैं देखता हूं कि अन्य ने आपको सुझाव दिया है कि आप बेस कन्स्ट्रक्टर को भेजने से पहले मूल्य को संशोधित कर सकते हैं। –

3

आप व्युत्पन्न वर्ग पर एक स्थिर विधि बना सकते हैं और आपकी तर्क रख सकते हैं:

public enum InputType { 
    Number = 1, 
    String = 2, 
    Date = 3 
} 

public class BaseClass { 
    public BaseClass(InputType t) { 
     // Logic 
    } 
} 

public class DerivedClass : BaseClass { 
    public DerivedClass(int i) 
     : base(GetInputType(i)) { 
     // Is it possible to set "value" here? 
     // Logic 
    } 

    private static InputType GetInputType(Int32 parameter) { 
     // Do something with parameter 
     // and return an InputType 

     return (InputType)Enum.Parse(typeof(InputType), parameter); 
    } 
} 
5

आप एक स्थिर विधि का उपयोग कर सकते हैं एक मूल्य की गणना करने के आधार निर्माता को पारित करने के लिए।

public class DerivedClass : 
    BaseClass 
{ 
    public 
    DerivedClass(int i) : 
     base(ComputedValue(i)) 
    { 
    } 

    public static InputType 
    ComputedValue(int i) 
    { 
     return InputType.Number; // or any other computation you want here 
    } 
} 
1

एक हैक शुरू करने के लिए एक अलग स्थिर विधि एक लैम्ब्डा या अनाम प्रतिनिधि उपयोग करने के लिए है बिना base() खंड में मनमाने ढंग से तर्क डाल करने के लिए। base() अंदर अभिव्यक्ति सभी निर्माता मानकों के दायरे में है, इसलिए आप स्वतंत्र रूप से उन्हें लैम्ब्डा के अंदर उपयोग कर सकते हैं। जैसे (मान लें कि यह सी # 2 है।0, इसलिए वहाँ एक ही बात के लिए एक एकल लाइनर लिखने के लिए) कोई LINQ है:

class Base 
{ 
    public Base(int[] xs) {} 
} 

class Derived : Base 
{ 
    public Derived(int first, int last) 
     : base(
      ((Func<int[]>)delegate 
      { 
       List<int> xs = new List<int>(); 
       for (int x = first; x < last; ++x) 
       { 
        xs.Add(x); 
       } 
       return xs.ToArray(); 
      })()) 
    { 
    } 
} 

हालांकि, मैं दृढ़ता से क्योंकि पठनीयता बिंदु देखने के इस सच में भयानक है से, व्यवहार में उपयोग करने के खिलाफ सलाह देंगे। एक स्थैतिक विधि के साथ आपको स्पष्ट रूप से कन्स्ट्रक्टर तर्कों को पारित करने की आवश्यकता होगी, लेकिन ऐसा नहीं है कि आपके पास आमतौर पर 3-4 से अधिक हैं।

+0

पावेल, क्या ऐसा करने का कोई तरीका है यदि बेस क्लास एक से अधिक कन्स्ट्रक्टर तर्क लेता है? –

+0

आप प्रत्येक तर्क के लिए एक अलग लैम्ब्डा प्राप्त कर सकते हैं, लेकिन आप उन लैम्बडा (कन्स्ट्रक्टर तर्कों को छोड़कर) के बीच चर साझा करने में सक्षम नहीं होंगे। –

+0

धन्यवाद पावेल - यह वही मुद्दा है जिसे मैं हल करने की कोशिश कर रहा हूं .. (लैम्बडास के बीच चर साझा करना)। असल में मैं कुछ तर्कों को समाहित करना चाहता हूं जो कुछ गणना करता है और तीन अलग-अलग (लेकिन संबंधित) फ़ील्ड देता है, जिनमें से प्रत्येक बेस क्लास के कन्स्ट्रक्टर के लिए एक अलग पैरामीटर शुरू करेगा। मैं स्थैतिक विधि दृष्टिकोण (जैसा कि आपने कहा था) के रूप में वापस जाकर, एक संरचना को लौटकर, प्रत्येक पैरामीटर के लिए एक बार स्थिर विधि को कॉल करके इस पर काम करना समाप्त कर दिया। यह हैकी है, लेकिन काम किया, क्योंकि मेरे परिदृश्य के लिए स्थैतिक विधि के आह्वान के बीच कोई दुष्प्रभाव नहीं हैं –

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