सामान्य प्रकार रूपांतरण स्ट्रिंग से


234

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

प्रकार हमेशा एक आदिम होना चाहिए। यह वर्ग एक अमूर्त वर्ग को उपवर्गित करता है जो मूल रूप से स्ट्रिंग के रूप में नाम और मूल्य को संग्रहीत करता है। यह विचार यह है कि यह उपवर्ग बेस क्लास में कुछ प्रकार की सुरक्षा को जोड़ देगा (साथ ही मुझे कुछ रूपांतरण में बचा सकता है)।

तो, मैंने एक वर्ग बनाया है जो (लगभग) यह है:

public class TypedProperty<DataType> : Property
{
    public DataType TypedValue
    {
        get { // Having problems here! }
        set { base.Value = value.ToString();}
    }
}

तो सवाल यह है:

वहाँ स्ट्रिंग से एक आदिम में बदलने के लिए एक "सामान्य" तरीका है?

मुझे ऐसा कोई भी जेनेरिक इंटरफ़ेस नहीं मिल रहा है जो बोर्ड में रूपांतरण को जोड़ता हो ( ITryParsable जैसा कुछ आदर्श हो सकता है!)।


मुझे आपके ठोस वर्ग का एक उदाहरण देखने में दिलचस्पी होगी, यहां तक ​​कि सिर्फ एक स्निपेट भी। :)
जॉन लिमजाप

क्या आप कृपया अपने आधार वर्ग के संबंधित भागों को पोस्ट कर सकते हैं?
JJS

मुझे आश्चर्य है कि अगर किसी को भी .net Standard 1.2: /
Dan Rayson

जवाबों:


374

मुझे यकीन नहीं है कि क्या मैं आपके इरादों को सही ढंग से समझ पाया हूं, लेकिन आइए देखें कि क्या यह मदद करता है।

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}

मैं कुछ दिनों से सोच रहा था कि एक सामान्य प्रकार में एक धारा को कैसे निष्क्रिय किया जाए। धन्यवाद :)
जाल

3
मैं सहमत हूं, हालांकि Convert.ChangeTypeयह बहुत सार्वभौमिक और एक्स्टेंसिबल समाधान नहीं है, यह अधिकांश बुनियादी प्रकारों के लिए काम करता है। अगर कुछ बेहतर करने की जरूरत है, तो इस विधि को टिम द्वारा सुझाई गई या पूरी तरह से अलग रूपांतरण पद्धति का उपयोग करने जैसी किसी चीज में लपेटने की कोई समस्या नहीं है।
लूबोस हैस्को

18
मैं निश्चित रूप से जहां जोड़ूंगा: T: IConvertible
MikeT

5
टाइप T IConvertible नहीं होना चाहिए, लेकिन Type of base.Value होना चाहिए।
13

74

लुबोस हैस्को की विधि अशक्तियों के लिए विफल हो जाती है। नीचे दी गई विधि नलिकाओं के लिए काम करेगी। मैं इसके साथ नहीं आया, हालांकि। मैंने इसे Google के माध्यम से पाया: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx "टूना टोकसोज़" को क्रेडिट

पहले उपयोग:

TConverter.ChangeType<T>(StringValue);  

कक्षा नीचे है।

public static class TConverter
{
    public static T ChangeType<T>(object value)
    {
        return (T)ChangeType(typeof(T), value);
    }

    public static object ChangeType(Type t, object value)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(t);
        return tc.ConvertFrom(value);
    }

    public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}

मैं Enums और अन्य जटिल संरचनाओं के लिए एक फॉलबैक कन्वर्ट विकल्प जोड़ूंगा, लेकिन अच्छी कॉल।
तोमर डब्ल्यू

2
RegisterTypeConverter क्यों? क्या हमें हाथ से पहले कन्वर्टर्स को पंजीकृत करने की आवश्यकता है? (दुर्भाग्य से लिंक मृत है, इसलिए मैं इस पर नहीं पढ़ सका)
कोहेन

एकाधिक रूपांतरणों के लिए आपको शायद tc(एक TypeConverter) केवल एक बार बनाना चाहिए । TypeConverterयह धीमा है क्योंकि यह खोज के लिए प्रतिबिंब का उपयोग करता है TypeConverterAttribute। यदि आप किसी एक निजी TypeConverterक्षेत्र को आरंभीकृत करते हैं , तो आपको TypeConverterकई बार फिर से उपयोग करने में सक्षम होना चाहिए ।
केविन पी। राइस

ठीक काम करता है, लेकिन अगर टी एक है object, एक अपवाद फेंकता है। मैं वर्कअराउंड करने में सक्षम था कि 'if (typeof (T) .IsPrimitive) का उपयोग करके {return TConverter.ChangeType <T> (StringValue); } और {ऑब्जेक्ट ओ = (ऑब्जेक्ट) स्ट्रिंगवैल्यू; को वापस; } उपयोग नमूने के प्रतिस्थापन के रूप में TConverter.ChangeType<T>(StringValue)
मैट

14

कई प्रकार (पूर्णांक, डबल, डेटटाइम आदि) के लिए, एक स्थिर पार्स विधि है। आप इसे प्रतिबिंब का उपयोग करके आह्वान कर सकते हैं:

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}

8
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptorवह वर्ग विधि है GetConvertorजो किसी Typeवस्तु को स्वीकार करती है और फिर आप उस निर्दिष्ट वस्तु ConvertFromको बदलने के valueलिए विधि कह सकते हैं ।


मुझे व्यक्तिगत रूप से लगता है कि यह इंटरफ़ेस विधि Convert.ChangeType के बजाय कनवर्ज़न को संभालने के लिए बेहतर है क्योंकि आपको अपने सभी वर्ग पर IConvertible इंटरफ़ेस को लागू करने की आवश्यकता है।
सौलहल

3

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

get { return StringConverter<DataType>.FromString(base.Value); }

अब, मुझे यह बताना चाहिए कि पैरामीटर किए गए प्रकारों के साथ मेरा अनुभव C ++ और उसके टेम्प्लेट तक सीमित है, लेकिन मुझे लगता है कि सी # जेनरिक का उपयोग करके उसी तरह का काम करने का कोई तरीका है।


सामान्य संस्करण C # में मौजूद नहीं हैं।
शिम्मी वेइटहैंडलर

3

स्टेटिक की जाँच करें Nullable.GetUnderlyingType। - यदि अंतर्निहित प्रकार अशक्त है, तो टेम्पलेट पैरामीटर नहीं है Nullable, और हम उस प्रकार का सीधे उपयोग कर सकते हैं - यदि अंतर्निहित प्रकार शून्य नहीं है, तो रूपांतरण में अंतर्निहित प्रकार का उपयोग करें।

लगता है मेरे लिए काम करता है:

public object Get( string _toparse, Type _t )
{
    // Test for Nullable<T> and return the base type instead:
    Type undertype = Nullable.GetUnderlyingType(_t);
    Type basetype = undertype == null ? _t : undertype;
    return Convert.ChangeType(_toparse, basetype);
}

public T Get<T>(string _key)
{
    return (T)Get(_key, typeof(T));
}

public void test()
{
    int x = Get<int>("14");
    int? nx = Get<Nullable<int>>("14");
}

1

बॉब के उत्तर से प्रेरणा लेकर , ये एक्सटेंशन शून्य मान रूपांतरण और सभी आदिम रूपांतरण का समर्थन करते हैं।

public static class ConversionExtensions
{
        public static object Convert(this object value, Type t)
        {
            Type underlyingType = Nullable.GetUnderlyingType(t);

            if (underlyingType != null && value == null)
            {
                return null;
            }
            Type basetype = underlyingType == null ? t : underlyingType;
            return System.Convert.ChangeType(value, basetype);
        }

        public static T Convert<T>(this object value)
        {
            return (T)value.Convert(typeof(T));
        }
}

उदाहरण

            string stringValue = null;
            int? intResult = stringValue.Convert<int?>();

            int? intValue = null;
            var strResult = intValue.Convert<string>();

0
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

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


धन्यवाद मुझे एक टी को एक इंटरफ़ेस में बदलना है और सरल रूपांतरण टी ऑब्जेक्ट सही ढंग से काम करता है, आसान और तेज़ धन्यवाद
LXG

5
(int) (वस्तु) "54"; एक भाग्य है !, यह VB नहीं है!
तोमर डब्ल्यू

0

मैंने लोबोस उत्तर का उपयोग किया और यह काम करता है। लेकिन मुझे संस्कृति सेटिंग के कारण युगल के रूपांतरण में समस्या थी । तो मैंने जोड़ा

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);

0

फिर भी एक और बदलाव। Nullables संभालती है, साथ ही ऐसी स्थितियां जहां स्ट्रिंग अशक्त है और T अशक्त नहीं है

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get
        {
            if (base.Value == null) return default(T);
            var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            return (T)Convert.ChangeType(base.Value, type);
        }
        set { base.Value = value.ToString(); }
    }
}

0

आप इसे नीचे के रूप में एक पंक्ति में कर सकते हैं:

YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));

खुश कोडिंग;)


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