C # में जेनेरिक एनम के लिए कास्ट इंट


84

C # में Enum करने के लिए Cast int के समान लेकिन मेरा Enum एक जेनेरिक टाइप पैरामीटर है। इससे निपटने का सबसे अच्छा तरीका क्या है ?

उदाहरण:

private T ConvertEnum<T>(int i) where T : struct, IConvertible
{
    return (T)i;
}

कंपाइलर त्रुटि उत्पन्न करता है Cannot convert type 'int' to 'T'

पूर्ण कोड निम्नानुसार है, जहां मूल्य में इंट, या अशक्त हो सकते हैं।

private int? TryParseInt(string value)
{
    var i = 0;
    if (!int.TryParse(value, out i))
    {
        return null;
    }
    return i;
}

private T? TryParseEnum<T>(string value) where T : struct, IConvertible
{
    var i = TryParseInt(value);
    if (!i.HasValue)
    {
        return null;
    }

    return (T)i.Value;
}

stackoverflow.com/questions/2745320/… - मदद कर सकता है?
सनी

पर अंतिम जवाब stackoverflow.com/questions/1331739/... , आप क्या चाहते हैं के करीब है। यह अभी भी चालाक नहीं है। मैं इसके लिए प्रतिबिंब का उपयोग करता हूं, आप कोड को बहुत मजबूत बना सकते हैं। मेरी राय में जेनेरिक के साथ खिलवाड़ करने के लिए संरचना पर्याप्त नहीं है।
टोनी हॉपकिंसन

जवाबों:


120

मैंने जो सबसे सरल तरीका पाया है वह है कि एक कास्ट को जोड़कर संकलक के हाथ को मजबूर करना object

return (T)(object)i.Value;


5
हम इंटम कास्टिंग कर रहे हैं, इसके विपरीत नहीं जैसा कि आप सवाल करते हैं। साथ ही, उस प्रश्न का कोई हल नहीं है।
MatteoSp

आप बस एनम मान के साथ एक स्थिर सरणी आवंटित कर सकते हैं, और फिर सही एनम प्राप्त करने के लिए इंडेक्स में पास करें। यह किसी भी तरह की कास्टिंग करने से बचाता है। उदाहरण (केवल लाइन 11,14, और 34 इस अवधारणा के लिए प्रासंगिक हैं): pastebin.com/iPEzttM4
16th पर Krythic

20

आपको इसके लिए उपयोग करने में सक्षम होना चाहिए Enum.Parse:

return (T)Enum.Parse(typeof(T), i.Value.ToString(), true);

इस लेख में विलुप्त होने के तरीकों के लिए सामान्य ज्ञान को शामिल करने की बात की गई है:


@Guvante: मुझे लगता है कि मैंने अपने उदाहरण में मूल्य को एक स्ट्रिंग में बदल दिया। क्या आप इस समस्या का कारण बनते हैं?
जेम्स जॉनसन

16

यहां एक बहुत तेज़ समाधान है जो इस तथ्य का दुरुपयोग करता है कि रनटाइम स्थिर सामान्य वर्गों के कई उदाहरण बनाता है। अपने आंतरिक अनुकूलन राक्षसों को दिलाने!

यह वास्तव में चमकता है जब आप एनम को सामान्य शैली में एक धारा से पढ़ रहे हैं। एक बाहरी वर्ग के साथ गठबंधन करें जो कमाल करने के लिए Enum के अंतर्निहित प्रकार और BitConverter को कैश करता है।

void Main() 
{
    Console.WriteLine("Cast (reference): {0}", (TestEnum)5);
    Console.WriteLine("EnumConverter: {0}", EnumConverter<TestEnum>.Convert(5));
    Console.WriteLine("Enum.ToObject: {0}", Enum.ToObject(typeof(TestEnum), 5));

    int iterations = 1000 * 1000 * 100;
    Measure(iterations, "Cast (reference)", () => { var t = (TestEnum)5; });
    Measure(iterations, "EnumConverter", () => EnumConverter<TestEnum>.Convert(5));
    Measure(iterations, "Enum.ToObject", () => Enum.ToObject(typeof(TestEnum), 5));
}

static class EnumConverter<TEnum> where TEnum : struct, IConvertible
{
    public static readonly Func<long, TEnum> Convert = GenerateConverter();

    static Func<long, TEnum> GenerateConverter()
    {
        var parameter = Expression.Parameter(typeof(long));
        var dynamicMethod = Expression.Lambda<Func<long, TEnum>>(
            Expression.Convert(parameter, typeof(TEnum)),
            parameter);
        return dynamicMethod.Compile();
    }
}

enum TestEnum 
{
    Value = 5
}

static void Measure(int repetitions, string what, Action action)
{
    action();

    var total = Stopwatch.StartNew();
    for (int i = 0; i < repetitions; i++)
    {
        action();
    }
    Console.WriteLine("{0}: {1}", what, total.Elapsed);
}

कोर i7-3740QM पर परिणाम अनुकूलन के साथ सक्षम:

Cast (reference): Value
EnumConverter: Value
Enum.ToObject: Value
Cast (reference): 00:00:00.3175615
EnumConverter: 00:00:00.4335949
Enum.ToObject: 00:00:14.3396366

2
यह वास्तव में अच्छा है, धन्यवाद। आप Expression.ConvertCheckedइसके बजाय उपयोग करना पसंद कर सकते हैं , ताकि एनम प्रकार की श्रेणी के संख्यात्मक अतिप्रवाह का परिणाम हो OverflowException
ड्रू नोक

आपका माइलेज अलग हो सकता है, मैंने try.dot.net (blazor) पर कोड चलाया और वहां EnumConverter <T> विकल्पों की तुलना में बहुत धीमा है। पहले वस्तु पर कास्टिंग प्रत्यक्ष कलाकारों की तुलना में लगभग 6 गुना धीमी थी, लेकिन अभी भी अन्य विकल्पों की तुलना में बेहतर है।
हरमन



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