2009-06-11 8 views
43

मेरे पास एक विधि है जो पैरामीटर के रूप में IList<T> का उपयोग करती है। मुझे यह जांचने की ज़रूरत है कि T ऑब्जेक्ट का प्रकार क्या है और इसके आधार पर कुछ करें। मैं T मान का उपयोग करने की कोशिश कर रहा था, लेकिन संकलक इसे अनुमति नहीं देता है। मेरा समाधान निम्न है:सी # जेनिक्स और टाइपिंग

private static string BuildClause<T>(IList<T> clause) 
{ 
    if (clause.Count > 0) 
    { 
     if (clause[0] is int || clause[0] is decimal) 
     { 
      //do something 
     } 
     else if (clause[0] is String) 
     { 
      //do something else 
     } 
     else if (...) //etc for all the types 
     else 
     { 
      throw new ApplicationException("Invalid type"); 
     } 
    } 
} 

ऐसा करने का एक बेहतर तरीका होना चाहिए। क्या कोई तरीका है कि मैं T के प्रकार की जांच कर सकता हूं जो कि पास हो गया है और फिर switch कथन का उपयोग करें?

+1

मैं व्यक्तिगत रूप से पता है कि आप प्रत्येक डेटा प्रकार के लिए विशेष कर रहे हैं चाहते हैं। यदि आप मोटे तौर पर प्रत्येक डेटा प्रकार के लिए एक ही रूपांतरण कर रहे हैं, तो विभिन्न प्रकारों को एक सामान्य इंटरफ़ेस में मैप करना और उस इंटरफ़ेस पर काम करना आसान हो सकता है। – Juliet

उत्तर

68

आप इस्तेमाल कर सकते हैं भार के:

public static string BuildClause(List<string> l){...} 

public static string BuildClause(List<int> l){...} 

public static string BuildClause<T>(List<T> l){...} 

या आप जेनेरिक पैरामीटर के प्रकार का निरीक्षण कर सकते हैं:

Type listType = typeof(T); 
if(listType == typeof(int)){...} 
+14

+1: डिजाइन और दीर्घकालिक रखरखाव के मामले में अधिभार निश्चित रूप से * सर्वोत्तम * समाधान हैं। जेनेरिक पैरामीटर का रनटाइम टाइप-चेक सीधे सीधा चेहरा के साथ कोड के लिए बहुत विडंबनापूर्ण लगता है। – Juliet

+0

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

+0

क्षमा किए बिना मूल स्ट्रिंग को वापस करें, क्षमा करें, क्या 'if-else' के बजाय 'स्विच-केस' का उपयोग करके इसे प्राप्त करने का कोई तरीका है? –

4

typeof ऑपरेटर ...

typeof(T) 

... सी # स्विच बयान के साथ काम नहीं करेगा। लेकिन इसके बारे में कैसे? निम्नलिखित पोस्ट एक स्थिर वर्ग में शामिल है ...

Is there a better alternative than this to 'switch on type'?

... कि दूँगी आप इस तरह कोड लिखने:

TypeSwitch.Do(
    sender, 
    TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"), 
    TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked), 
    TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over")); 
+0

यहां जेरेडपार का जवाब भी देखें। –

11

आप typeof(T) का उपयोग कर सकते हैं।

private static string BuildClause<T>(IList<T> clause) 
{ 
    Type itemType = typeof(T); 
    if(itemType == typeof(int) || itemType == typeof(decimal)) 
    ... 
} 
1

आप typeOf(T) कर सकते हैं, लेकिन मैं अपने विधि दोबारा जांच करें और सुनिश्चित करें कि आपके यहां एक फ्रॅन्स का उल्लंघन नहीं होगा। यह एक कोड गंध होगा, और यह कहना नहीं है कि यह नहीं किया जाना चाहिए, लेकिन आपको सावधान रहना चाहिए।

जेनिक्स का बिंदु टाइप-अज्ञेयवादी अल्गर्थिम्स बनाने में सक्षम है, आप इस बात की परवाह नहीं करते कि यह किस प्रकार है या जब तक यह मानदंड के एक निश्चित सेट के भीतर फिट बैठता है। आपका कार्यान्वयन बहुत सामान्य नहीं है।

1

स्विच स्टेटमेंट का उपयोग करने के लिए कोई तरीका नहीं है कि आप इसे क्या करना चाहते हैं। स्विच स्टेटमेंट को अभिन्न प्रकारों के साथ आपूर्ति की जानी चाहिए, जिसमें जटिल प्रकार जैसे "टाइप" ऑब्जेक्ट, या उस मामले के लिए कोई अन्य ऑब्जेक्ट प्रकार शामिल नहीं है।

2

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

6

डिफ़ॉल्ट रूप से पता है कि कोई शानदार तरीका नहीं है। थोड़ी देर पहले मैं इसके साथ निराश हो गया और एक छोटी उपयोगिता कक्षा लिखी जिसने थोड़ा सा मदद की और सिंटैक्स को थोड़ा क्लीनर बनाया।मूलतः यह

TypeSwitcher.Do(clause[0], 
    TypeSwitch.Case<int>(x => ...), // x is an int 
    TypeSwitch.Case<decimal>(d => ...), // d is a decimal 
    TypeSwitch.Case<string>(s => ...)); // s is a string 

पूर्ण ब्लॉग पोस्ट में कोड और विवरण कार्यान्वयन पर कर रहे हैं कि हर प्रकार की जाँच और प्रकार के आधार पर कुछ कर रही कहते हैं के लिए यहां उपलब्ध

2

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

उदाहरण के लिए यदि आपके पास एक वर्ग है जो कहता है कि इस तरह कार्यान्वित किया गया है (नोट: मैं यह सब कुछ नहीं दिखा रहा हूं कि यह कोड सादगी के लिए करता है और यहां आसानी से कट और पेस्ट किया गया है, इसलिए यह संभवतः निर्माण या काम नहीं कर सकता पूरे कोड करता है, लेकिन यह बात भर में एक enum इसके अलावा, यूनिट है) हो जाता है:।

public class FoodCount<TValue> : BaseFoodCount 
{ 
    public TValue Value { get; set; } 

    public override string ToString() 
    { 
     if (Value is decimal) 
     { 
      // Code not cleaned up yet 
      // Some code and values defined in base class 

      mstrValue = Value.ToString(); 
      decimal mdecValue; 
      decimal.TryParse(mstrValue, out mdecValue); 

      mstrValue = decimal.Round(mdecValue).ToString(); 

      mstrValue = mstrValue + mstrUnitOfMeasurement; 
      return mstrValue; 
     } 
     else 
     { 
      // Simply return a string 
      string str = Value.ToString() + mstrUnitOfMeasurement; 
      return str; 
     } 
    } 
} 

...

public class SaturatedFat : FoodCountWithDailyValue<decimal> 
{ 
    public SaturatedFat() 
    { 
     mUnit = Unit.g; 
    } 

} 

public class Fiber : FoodCount<int> 
{ 
    public Fiber() 
    { 
     mUnit = Unit.g; 
    } 
} 

public void DoSomething() 
{ 
     nutritionFields.SaturatedFat oSatFat = new nutritionFields.SaturatedFat(); 

     string mstrValueToDisplayPreFormatted= oSatFat.ToString(); 
} 

तो सारांश में, मुझे लगता है कि वैध कारणों से आप कर सकते हैं कर रहे हैं कुछ विशेष करने के लिए, जेनेरिक किस प्रकार का है, यह देखने के लिए जांचें।

0

इस बारे में कैसे:

  // Checks to see if the value passed is valid. 
      if (!TypeDescriptor.GetConverter(typeof(T)).IsValid(value)) 
      { 
       throw new ArgumentException(); 
      } 
संबंधित मुद्दे