मैं रिटर्न विधि को सामान्य कैसे बनाऊं?


166

क्या इस पद्धति को सामान्य बनाने का कोई तरीका है ताकि मैं एक स्ट्रिंग, बूल, इंट, या डबल लौटा सकूं? अभी, यह एक स्ट्रिंग लौटा रहा है, लेकिन अगर यह कॉन्फ़िगरेशन मान के रूप में "सही" या "गलत" खोजने में सक्षम है, तो मैं उदाहरण के लिए एक बूल वापस करना चाहूंगा।

    public static string ConfigSetting(string settingName)
    {  
         return ConfigurationManager.AppSettings[settingName];
    }

क्या आपके लिए यह जानने का कोई तरीका है कि प्रत्येक सेटिंग किस प्रकार की है?
thecoshman

2
मुझे लगता है कि आप जो प्रश्न पूछना चाहते हैं, वह यह है कि "मैं अपने एप्लिकेशन कॉन्फिग को कैसे दृढ़ता से टाइप करूं?" हालांकि, जब तक मैंने उचित उत्तर लिखने के लिए काम किया है, तब तक बहुत लंबा हो चुका है।
सिमोन

याह, आदर्श रूप से मैं इस विधि में टाइप पास करना नहीं चाहता। मैं केवल 4 प्रकारों का उल्लेख करने जा रहा हूं। इसलिए यदि "सही" / "गलत" सेट किया गया है, तो मैं चाहता हूं कि यह फ़ंक्शन एक बूलियन (इसे विधि में पारित करने की आवश्यकता के बिना) लौटे, मैं शायद इंट और डबल को सिर्फ डबल में जोड़ सकता हूं, और बाकी सब कुछ एक स्ट्रिंग होना चाहिए। जो पहले से ही उत्तर दिया गया है वह ठीक काम करेगा, लेकिन मुझे हर बार टाइप पास करना होगा, जो शायद ठीक है।
मैकगियर

3
आपकी टिप्पणी से ऐसा लगता है कि आप एक ऐसी विधि के लिए पूछ रहे हैं जो सेटिंग नाम की कुंजी के लिए प्राप्त वास्तविक डेटा के आधार पर रन-टाइम पर एक दृढ़ता से टाइप किया हुआ बूल (या स्ट्रिंग, या इंट, या आपके पास क्या है) लौटेगी । C # आपके लिए ऐसा नहीं करेगा; ऐसा कोई तरीका नहीं है जिससे आप संकलन समय पर उस मान के प्रकार को जान सकें। दूसरे शब्दों में, यह डायनेमिक टाइपिंग है, स्टैटिक टाइपिंग नहीं। यदि आप dynamicकीवर्ड का उपयोग करते हैं तो C # आपके लिए ऐसा कर सकता है । उसके लिए एक प्रदर्शन लागत है, लेकिन एक कॉन्फ़िग फ़ाइल पढ़ने के लिए, प्रदर्शन लागत लगभग निश्चित रूप से महत्वहीन है।
फोग

जवाबों:


354

आपको इसे एक सामान्य विधि बनाने की आवश्यकता है, जैसे:

public static T ConfigSetting<T>(string settingName)
{  
    return /* code to convert the setting to T... */
}

लेकिन कॉलर को उस प्रकार को निर्दिष्ट करना होगा जो वे अपेक्षा करते हैं। तब आप संभावित रूप से उपयोग कर सकते हैं Convert.ChangeType, यह मानते हुए कि सभी प्रासंगिक प्रकार समर्थित हैं:

public static T ConfigSetting<T>(string settingName)
{  
    object value = ConfigurationManager.AppSettings[settingName];
    return (T) Convert.ChangeType(value, typeof(T));
}

मैं पूरी तरह से आश्वस्त नहीं हूं कि यह सब एक अच्छा विचार है, आप मन ...


21
/ * कोड को टी में बदलने के लिए कोड ... * / और यहाँ पूरे उपन्यास का अनुसरण किया जाता है :)
एड्रियन इफोडे

1
क्या इससे आपको यह जानने की आवश्यकता नहीं होगी कि आप किस प्रकार की सेटिंग प्राप्त करना चाहते हैं, जो संभव नहीं है।
thecoshman

2
@thecoshman: यह होगा, लेकिन अगर आप तब नहीं करते थे तो आप लौटे मूल्य के साथ क्या करते हैं?
जॉर्ज डकेट

5
हालांकि यह उत्तर निश्चित रूप से सही है, और जैसा कि आप नोट करते हैं कि ओपी के अनुरोध को संतुष्ट करता है, यह शायद ध्यान देने योग्य है कि अलग-अलग तरीकों ( ConfigSettingStringऔर ConfigSettingBool, आदि) के पुराने दृष्टिकोण में उन निकायों का लाभ है जो छोटे, स्पष्ट और बेहतर केंद्रित होंगे ।
फोग

4
यदि यह अनुशंसित नहीं है तो सामान्य रिटर्न प्रकारों का उद्देश्य क्या है?
बॉबीलेक्स

29

आप उपयोग कर सकते हैं Convert.ChangeType():

public static T ConfigSetting<T>(string settingName)
{
    return (T)Convert.ChangeType(ConfigurationManager.AppSettings[settingName], typeof(T));
}

13

इसे करने के कई तरीके हैं (प्राथमिकता के आधार पर, ओपी की समस्या के लिए विशिष्ट)

  1. विकल्प 1: सीधे दृष्टिकोण - प्रत्येक प्रकार के लिए कई फ़ंक्शन बनाएं जो आप एक सामान्य फ़ंक्शन के बजाय अपेक्षा करते हैं।

    public static bool ConfigSettingInt(string settingName)
    {  
         return Convert.ToBoolean(ConfigurationManager.AppSettings[settingName]);
    }
  2. विकल्प 2: जब आप रूपांतरण के फैंसी तरीकों का उपयोग नहीं करना चाहते हैं - मूल्य को ऑब्जेक्ट पर और फिर जेनेरिक प्रकार पर कास्ट करें।

    public static T ConfigSetting<T>(string settingName)
    {  
         return (T)(object)ConfigurationManager.AppSettings[settingName];
    }

    नोट - यदि कास्ट मान्य नहीं है (आपका मामला) तो यह एक त्रुटि है। यदि आप टाइप कास्टिंग के बारे में सुनिश्चित नहीं हैं, तो मैं ऐसा करने की सिफारिश नहीं करूंगा, बल्कि विकल्प 3 पर जाएं।

  3. विकल्प 3: प्रकार की सुरक्षा के साथ सामान्य - प्रकार रूपांतरण को संभालने के लिए एक सामान्य कार्य बनाएँ।

    public static T ConvertValue<T,U>(U value) where U : IConvertible
    {
        return (T)Convert.ChangeType(value, typeof(T));
    } 

    नोट - T एक अपेक्षित प्रकार है, ध्यान दें कि यहाँ पर कसाव है (U का प्रकार हमें त्रुटियों से बचाने के लिए IConvertible होना चाहिए)


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

7

आपको अपने प्रकार के रिटर्न मान को जेनेरिक प्रकार में बदलना होगा जिसे आप कॉल करने के दौरान विधि में पास करते हैं।

    public static T values<T>()
    {
        Random random = new Random();
        int number = random.Next(1, 4);
        return (T)Convert.ChangeType(number, typeof(T));
    }

आपको एक प्रकार पास करने की आवश्यकता है जो उस पद्धति के माध्यम से आपके द्वारा लौटाए जाने वाले मूल्य के लिए टाइप करने योग्य हो।

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


ऑन द स्पॉट - मेरे लिए अंतिम पंक्ति return (T)Convert.ChangeType(number, typeof(T));वही थी जो मुझे याद आ रही थी - चीयर्स
ग्रेग ट्रेवेलिक

1

एक फ़ंक्शन बनाएं और सामान्य प्रकार के रूप में पुट पैरामीटर पास करें।

 public static T some_function<T>(T out_put_object /*declare as Output object*/)
    {
        return out_put_object;
    }

यह वास्तव में कुछ उपयोग के मामलों के लिए बहुत स्मार्ट है। जैसे डाटा को किसी डेटाबेस से बाहर निकालना। आपको पता है कि आपको टाइप T के डेटा की एक सूची मिल जाएगी। लोडिंग विधि को यह नहीं पता है कि आप अभी किस प्रकार का T चाहते हैं। तो बस इसके लिए एक नई सूची <WantedObject> पास करें और यह विधि काम कर सकती है और इसे वापस करने से पहले सूची भरें। अच्छा!
मार्को हीमैन

0

कृपया नीचे दिए गए कोड का प्रयास करें:

public T? GetParsedOrDefaultValue<T>(string valueToParse) where T : struct, IComparable
{
 if(string.EmptyOrNull(valueToParse))return null;
  try
  {
     // return parsed value
     return (T) Convert.ChangeType(valueToParse, typeof(T));
  }
  catch(Exception)
  {
   //default as null value
   return null;
  }
 return null;
}

-1
 private static T[] prepareArray<T>(T[] arrayToCopy, T value)
    {
        Array.Copy(arrayToCopy, 1, arrayToCopy, 0, arrayToCopy.Length - 1);
        arrayToCopy[arrayToCopy.Length - 1] = value;
        return (T[])arrayToCopy;
    }

मैं अपने पूरे कोड में यह प्रदर्शन कर रहा था और इसे एक विधि में रखना चाहता था। मैं इसे यहाँ साझा करना चाहता था क्योंकि मुझे अपने रिटर्न मान के लिए Convert.ChangeType का उपयोग नहीं करना था। यह एक सर्वोत्तम अभ्यास नहीं हो सकता है लेकिन यह मेरे लिए काम करता है। यह विधि सामान्य प्रकार के एक सरणी में और सरणी के अंत में जोड़ने के लिए एक मान लेती है। फिर सरणी को पहले मूल्य के छीनने के साथ कॉपी किया जाता है और विधि में लिया गया मूल्य सरणी के अंत में जोड़ा जाता है। आखिरी बात यह है कि मैं सामान्य सरणी लौटाता हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.