टी

2009-05-22 22 views
59

पर ऑब्जेक्ट कास्ट करें। मैं .NET में XmlReader कक्षा के साथ एक XML फ़ाइल को पार्स कर रहा हूं और मैंने सोचा कि सामान्य रूप से विभिन्न विशेषताओं को पढ़ने के लिए जेनेरिक पार्स फ़ंक्शन लिखना स्मार्ट होगा। मैं निम्नलिखित फ़ंक्शन के साथ आया:टी

private static T ReadData<T>(XmlReader reader, string value) 
{ 
    reader.MoveToAttribute(value); 
    object readData = reader.ReadContentAsObject(); 
    return (T)readData; 
} 

जैसा कि मुझे एहसास हुआ, यह पूरी तरह से काम नहीं करता है जैसा मैंने योजना बनाई है; यह int या double जैसे आदिम प्रकारों के साथ एक त्रुटि फेंकता है, क्योंकि एक कास्ट string से एक संख्यात्मक प्रकार में परिवर्तित नहीं हो सकता है। संशोधित रूप में मेरे फ़ंक्शन के प्रबल होने का कोई तरीका है?

उत्तर

144

पहले यह देखने के लिए जांचें कि क्या इसे कास्ट किया जा सकता है।

if (readData is T) { 
    return (T)readData; 
} 
try { 
    return (T)Convert.ChangeType(readData, typeof(T)); 
} 
catch (InvalidCastException) { 
    return default(T); 
} 
+1

मैं करने के लिए Convert.ChangeType के साथ लाइन बदल दिया है: 'वापसी (टी) Convert.ChangeType (readData, typeof (टी), System.Globalization.CultureInfo.InstalledUICulture.NumberFormat) यह विभिन्न विभिन्न सांस्कृतिक पर काम करने के लिए विन्यास। –

+1

उत्कृष्ट जवाब। मंचों पर दिनों की तलाश कर रहे थे लेकिन इस तरह कोई उचित जवाब नहीं मिला। धन्यवाद बॉब –

+1

मुझे लगता है कि आप कर सकते हैं (टी) (ऑब्जेक्ट) readData – jjxtra

15

क्या आपने Convert.ChangeType को आजमाया है?

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

private static T ReadData<T>(XmlReader reader, string value) 
{ 
    reader.MoveToAttribute(value); 
    object readData = reader.ReadContentAsObject(); 
    return (T)Convert.ChangeType(readData, typeof(T)); 
} 
+0

मैंने शुरुआत में कनवर्ट पर एक नज़र डाली थी। चेंज टाइप ने फैसला किया कि यह कुछ ऑपरेशन के लिए इस ऑपरेशन के लिए उपयोगी नहीं था। आप और बॉब दोनों ने एक ही जवाब प्रदान किया, और मैंने आपके उत्तरों के बीच मिश्रण के साथ जाने का फैसला किया, इसलिए मैंने कोशिश कथन का उपयोग करने से परहेज किया लेकिन जब भी संभव हो तो 'रिटर्न (टी) रीडडाटा' का उपयोग किया। –

1

एक 'क्लास' स्थिर बिंदु जोड़ें (या अधिक विस्तृत, एक आधार वर्ग या इंटरफ़ेस आपके exepected टी वस्तुओं की) की तरह:

private static T ReadData<T>(XmlReader reader, string value) where T : class 
{ 
    reader.MoveToAttribute(value); 
    object readData = reader.ReadContentAsObject(); 
    return (T)readData; 
} 

या where T : IMyInterface या where T : new(), आदि

2

आप शायद क़दम कर सकते हैं एस में, एक पैरामीटर है, जो स्ट्रिंग से टी

में बदल जाएगा
3

आप प्रकार की आवश्यकता हो सकती एक संदर्भ प्रकार होना एक प्रतिनिधि के रूप:

private static T ReadData<T>(XmlReader reader, string value) where T : class 
{ 
    reader.MoveToAttribute(value); 
    object readData = reader.ReadContentAsObject(); 
    return (T)readData; 
} 

और फिर एक और कर मूल्य प्रकार और TryParse का उपयोग करता है ...

private static T ReadDataV<T>(XmlReader reader, string value) where T : struct 
{ 
    reader.MoveToAttribute(value); 
    object readData = reader.ReadContentAsObject(); 
    int outInt; 
    if(int.TryParse(readData, out outInt)) 
     return outInt 
    //... 
} 
+0

दूसरी विधि काम नहीं करती है, क्या यह करता है। – mtman

1

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

शायद इसे ट्राईपर्स विधि के रूप में बनाने के लिए और अधिक समझदारी होगी जो टी में पढ़ने का प्रयास करता है, लेकिन अगर यह नहीं किया जा सकता है तो झूठी वापसी करता है?

private static bool ReadData<T>(XmlReader reader, string value, out T data) 
    { 
     bool result = false; 
     try 
     { 
      reader.MoveToAttribute(value); 
      object readData = reader.ReadContentAsObject(); 
      data = readData as T; 
      if (data == null) 
      { 
       // see if we can convert to the requested type 
       data = (T)Convert.ChangeType(readData, typeof(T)); 
      } 
      result = (data != null); 
     } 
     catch (InvalidCastException) { } 
     catch (Exception ex) 
     { 
      // add in any other exception handling here, invalid xml or whatnot 
     } 
     // make sure data is set to a default value 
     data = (result) ? data : default(T); 
     return result; 
    } 

संपादित करें: अब जब मैं इसके बारे में सोचता हूं, तो क्या मुझे वास्तव में convert.changetype परीक्षण करने की आवश्यकता है? क्या लाइन पहले से ही ऐसा करने की कोशिश नहीं करती है? मुझे यकीन नहीं है कि उस अतिरिक्त चेंजटाइप कॉल को वास्तव में कुछ भी पूरा करता है। असल में, यह अपवाद उत्पन्न करके प्रसंस्करण ओवरहेड को बढ़ा सकता है। अगर कोई ऐसा अंतर जानता है जो इसे करने लायक बनाता है, तो कृपया पोस्ट करें!

2

असल में, समस्या यहां ReadContentAsObject का उपयोग है। दुर्भाग्य से, यह विधि इसकी अपेक्षाओं तक नहीं जीती है; जबकि इसे मूल्य के लिए सबसे अधिक एप्राप्रिरेट प्रकार का पता लगाना चाहिए, यह वास्तव में एक स्ट्रिंग देता है, इससे कोई फर्क नहीं पड़ता कि (यह परावर्तक का उपयोग करके सत्यापित किया जा सकता है)।

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

इसके बजाय ReadContentAs का उपयोग करने का प्रयास करें, यह वही है जो आपको चाहिए।

private static T ReadData<T>(XmlReader reader, string value) 
{ 
    reader.MoveToAttribute(value); 
    object readData = reader.ReadContentAs(typeof(T), null); 
    return (T)readData; 
} 
+0

काफी कॉम्पैक्ट और सुरुचिपूर्ण लग रहा है। हालांकि, स्वीकृत उत्तर में समाधान चेंजटाइप का उपयोग करता है जो कई अलग-अलग संस्कृतियों के साथ संगत है क्योंकि यह IFormatProvider स्वीकार करता है। चूंकि यह परियोजना के लिए एक सभ्यता है, इसलिए मैं उस समाधान को जारी रखूंगा। –

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