এনুম মানটির জন্য কীভাবে ট্রাইপার্স করবেন?


97

আমি একটি ফাংশন লিখতে চাই যা একটি এর সম্ভাব্য মানের বিপরীতে প্রদত্ত মানকে (স্ট্রিং হিসাবে পাস করা) বৈধতা দিতে পারে enum। ম্যাচের ক্ষেত্রে, এটি এনাম উদাহরণটি ফিরিয়ে আনতে হবে; অন্যথায়, এটি একটি ডিফল্ট মান প্রদান করা উচিত।

ফাংশনটি অভ্যন্তরীণভাবে try/ ব্যবহার করতে পারে না catch, যা ব্যবহার বাদ দেয় Enum.Parseযা কোনও অবৈধ যুক্তি দেওয়া হলে ব্যতিক্রম ছুঁড়ে দেয়।

এটি TryParseবাস্তবায়নের জন্য আমি কোনও ফাংশনের লাইনে কিছু ব্যবহার করতে চাই :

public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
   object enumValue;
   if (!TryParse (typeof (TEnum), strEnumValue, out enumValue))
   {
       return defaultValue;
   }
   return (TEnum) enumValue;
}

8
আমি এই প্রশ্নটি বুঝতে পারি না; আপনি বলছেন "আমি এই সমস্যাটি সমাধান করতে চাই, তবে আমি কোনও পদ্ধতি ব্যবহার করতে চাই না যা আমাকে সমাধান দেয়।" আলোচ্য বিষয়টি কি?
ডমেনিক

4
সমাধান / ধরার চেষ্টা করার জন্য আপনার বিরক্তি কী? যদি আপনি ব্যতিক্রমগুলি ব্যয়বহুল হয়ে ওঠার চেষ্টা করছেন তবে তারা 'ব্যয়বহুল', দয়া করে নিজেকে বিরতি দিন। 99% ক্ষেত্রে, আপনার মূল কোডের তুলনায় মূল্য ব্যতিক্রম নিক্ষেপ / ধরা ব্যয় নগন্য।
সমাধান

4
@ ডোমেনিক: আমি ইতিমধ্যে যা জানি তার থেকে আমি আরও ভাল সমাধানের সন্ধান করছি। আপনি কি ইতিমধ্যে জানেন এমন কোনও রুট বা ট্রেন জিজ্ঞাসা করতে কোনও রেলওয়ে তদন্তে যাবেন :)
মনিশ বসন্তানী

4
@ যোগী, @ থোররিন: চেষ্টা করুন ... ধরা সবসময়ই আমার শেষ পছন্দ হবে। ব্যয়বহুল হওয়া সম্পর্কে, আমরা কখনই জানি না। যদি কেউ 100 টি আইটেমের তালিকার উপরে আমার ইউটিলিটি পদ্ধতিটি কল করে?
মণীশ বাসন্তানী

4
এম্বি, কেবল একটি চেষ্টা / ক্যাচ ব্লকে প্রবেশের ব্যয় নগদ নয়। ব্যতিক্রম ছোঁড়ার ব্যয়টি নয়, তবে তারপরে ব্যতিক্রমী হওয়ার কথা, না? এছাড়াও, "আমরা কখনই জানি না" ... কোডটি প্রোফাইল করুন এবং খুঁজে বের করবেন না। কিছুটা ধীর হয়ে আছে কিনা তা ভেবে আপনার সময় নষ্ট করবেন না, খুঁজে বের করুন!
আকমাদ

উত্তর:


31

অন্যরা যেমন বলেছে, আপনাকে নিজের প্রয়োগ করতে হবে TryParse। সাইমন মাউরিয়ার একটি সম্পূর্ণ বাস্তবায়ন সরবরাহ করছে যা সবকিছুর যত্ন নেয়।

আপনি যদি বিটফিল্ড এনামগুলি (অর্থাত্ পতাকাগুলি) ব্যবহার করছেন তবে আপনাকে এমন দুটি স্ট্র্যামও পরিচালনা করতে হবে "MyEnum.Val1|MyEnum.Val2"যা দুটি এনাম মানগুলির সংমিশ্রণ। আপনি যদি কেবল Enum.IsDefinedএই স্ট্রিং দিয়ে কল করেন তবে Enum.Parseএটি সঠিকভাবে পরিচালনা করলেও এটি মিথ্যা ফিরে আসবে ।

হালনাগাদ

মন্তব্যগুলিতে লিসা এবং খ্রিস্টান দ্বারা উল্লিখিত হিসাবে, Enum.TryParseএখন নেট # 4 এবং আরও জন্য সি # তে উপলব্ধ।

এমএসডিএন ডক্স


সম্ভবত অন্তত সেক্সি কিন্তু আমি সম্মত এই হ 'ল সেরা আপনার কোড .NET 4. চলে আসেন করা হয় যতক্ষণ না
লিসা

4
নীচে উল্লিখিত হিসাবে, তবে সত্যই দৃশ্যমান নয়: নেট 4 এনাম হিসাবে। ট্রাইপার্স উপলব্ধ এবং অতিরিক্ত কোডিং ছাড়াই কাজ করে। আরও তথ্য এমএসডিএন থেকে পাওয়া যায়: এমএসডিএন.মাইক্রোসফট.লিবেরি / ভিস্টুডিও
খ্রিস্টান

106

এনাম.আইএসডিফাইনড জিনিসগুলি সম্পন্ন করবে। এটি ট্রাই পার্সির মতো দক্ষ নাও হতে পারে, তবে এটি ব্যতিক্রম পরিচালনা না করে কাজ করবে।

public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
    if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
        return defaultValue;

    return (TEnum)Enum.Parse(typeof(TEnum), strEnumValue);
}

মূল্যবান লক্ষ্য করা যায়: TryParse.NET 4.0 এ একটি পদ্ধতি যুক্ত করা হয়েছিল।


4
আমি এখনও অবধি দেখা সেরা উত্তর ... কোন চেষ্টা / ধরা, কোনও গেটনামস :) নেই
টমাস

13
এনাম.আইএসডিফাইন্ডডের ত্রুটিগুলি: ব্লগস.এমএসএনএন
নাদের শিরাজি

6
আইসডিফাইন্ডে কোনও উপেক্ষাের মামলা নেই
অ্যান্টনি জনস্টন

4
@ অ্যান্টনি: আপনি যদি মামলার সংবেদনশীলতা সমর্থন করতে চান তবে আপনার প্রয়োজন হবে GetNames। অভ্যন্তরীণভাবে, এই সমস্ত পদ্ধতি (সহ Parse) ব্যবহার করে GetHashEntry, যা আসল প্রতিবিম্বটি করে - একবার। উজ্জ্বল দিকে, .NET 4.0 এর একটি ট্রাই পার্স রয়েছে এবং এটি জেনেরিকও :)
থোররিন

+1 এটি আমার দিন বাঁচায়! আমি .NET 4 থেকে .NET 3.5 থেকে একটি গুচ্ছ কোড ব্যাকপোর্ট করছি এবং আপনি আমাকে সংরক্ষণ করেছেন :)
ডাইটাঙ্গিও

20

এখানে একটি কাস্টম বাস্তবায়ন EnumTryParse । অন্যান্য সাধারণ বাস্তবায়নের বিপরীতে, এটি Flagsগুণকে চিহ্নিত করা এনুমকেও সমর্থন করে ।

    /// <summary>
    /// Converts the string representation of an enum to its Enum equivalent value. A return value indicates whether the operation succeeded.
    /// This method does not rely on Enum.Parse and therefore will never raise any first or second chance exception.
    /// </summary>
    /// <param name="type">The enum target type. May not be null.</param>
    /// <param name="input">The input text. May be null.</param>
    /// <param name="value">When this method returns, contains Enum equivalent value to the enum contained in input, if the conversion succeeded.</param>
    /// <returns>
    /// true if s was converted successfully; otherwise, false.
    /// </returns>
    public static bool EnumTryParse(Type type, string input, out object value)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        if (!type.IsEnum)
            throw new ArgumentException(null, "type");

        if (input == null)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        input = input.Trim();
        if (input.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        string[] names = Enum.GetNames(type);
        if (names.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        Type underlyingType = Enum.GetUnderlyingType(type);
        Array values = Enum.GetValues(type);
        // some enums like System.CodeDom.MemberAttributes *are* flags but are not declared with Flags...
        if ((!type.IsDefined(typeof(FlagsAttribute), true)) && (input.IndexOfAny(_enumSeperators) < 0))
            return EnumToObject(type, underlyingType, names, values, input, out value);

        // multi value enum
        string[] tokens = input.Split(_enumSeperators, StringSplitOptions.RemoveEmptyEntries);
        if (tokens.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        ulong ul = 0;
        foreach (string tok in tokens)
        {
            string token = tok.Trim(); // NOTE: we don't consider empty tokens as errors
            if (token.Length == 0)
                continue;

            object tokenValue;
            if (!EnumToObject(type, underlyingType, names, values, token, out tokenValue))
            {
                value = Activator.CreateInstance(type);
                return false;
            }

            ulong tokenUl;
            switch (Convert.GetTypeCode(tokenValue))
            {
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                    tokenUl = (ulong)Convert.ToInt64(tokenValue, CultureInfo.InvariantCulture);
                    break;

                //case TypeCode.Byte:
                //case TypeCode.UInt16:
                //case TypeCode.UInt32:
                //case TypeCode.UInt64:
                default:
                    tokenUl = Convert.ToUInt64(tokenValue, CultureInfo.InvariantCulture);
                    break;
            }

            ul |= tokenUl;
        }
        value = Enum.ToObject(type, ul);
        return true;
    }

    private static char[] _enumSeperators = new char[] { ',', ';', '+', '|', ' ' };

    private static object EnumToObject(Type underlyingType, string input)
    {
        if (underlyingType == typeof(int))
        {
            int s;
            if (int.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(uint))
        {
            uint s;
            if (uint.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(ulong))
        {
            ulong s;
            if (ulong.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(long))
        {
            long s;
            if (long.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(short))
        {
            short s;
            if (short.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(ushort))
        {
            ushort s;
            if (ushort.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(byte))
        {
            byte s;
            if (byte.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(sbyte))
        {
            sbyte s;
            if (sbyte.TryParse(input, out s))
                return s;
        }

        return null;
    }

    private static bool EnumToObject(Type type, Type underlyingType, string[] names, Array values, string input, out object value)
    {
        for (int i = 0; i < names.Length; i++)
        {
            if (string.Compare(names[i], input, StringComparison.OrdinalIgnoreCase) == 0)
            {
                value = values.GetValue(i);
                return true;
            }
        }

        if ((char.IsDigit(input[0]) || (input[0] == '-')) || (input[0] == '+'))
        {
            object obj = EnumToObject(underlyingType, input);
            if (obj == null)
            {
                value = Activator.CreateInstance(type);
                return false;
            }
            value = obj;
            return true;
        }

        value = Activator.CreateInstance(type);
        return false;
    }

4
আপনি সর্বোত্তম বাস্তবায়ন সরবরাহ করেছেন এবং আমি এটি নিজের উদ্দেশ্যে ব্যবহার করেছি; তবে আমি ভাবছি আপনি Activator.CreateInstance(type)ডিফল্ট এনাম মান তৈরি করতে এবং কেন ব্যবহার করেন না Enum.ToObject(type, 0)। শুধু স্বাদের বিষয়?
পিয়ের আরনাড

4
@ পিয়ার - হুমমম ... না, এ সময়টি এটি আরও প্রাকৃতিক বলে মনে হয়েছিল :-) সম্ভবত এনুম.টোঅবজেক্টটি অভ্যন্তরীণভাবে অভ্যন্তরীণ একটি অভ্যন্তরীণ কল ইন্টার্নালবক্সইনাম ব্যবহার করায় এটি আরও দ্রুত? আমি কখনই এটি চেক করিনি ...
সাইমন মউরিয়ার

4
নীচে উল্লিখিত হিসাবে, তবে সত্যই দৃশ্যমান নয়: নেট 4 এনাম হিসাবে। ট্রাইপার্স উপলব্ধ এবং অতিরিক্ত কোডিং ছাড়াই কাজ করে। আরও তথ্য এমএসডিএন থেকে পাওয়া যায়: এমএসডিএন.মাইক্রোসফট.লিবেরি / ভিস্টুডিও
খ্রিস্টান

16

শেষ অবধি আপনাকে এটিকে চারপাশে বাস্তবায়ন করতে হবে Enum.GetNames:

public bool TryParseEnum<T>(string str, bool caseSensitive, out T value) where T : struct {
    // Can't make this a type constraint...
    if (!typeof(T).IsEnum) {
        throw new ArgumentException("Type parameter must be an enum");
    }
    var names = Enum.GetNames(typeof(T));
    value = (Enum.GetValues(typeof(T)) as T[])[0];  // For want of a better default
    foreach (var name in names) {
        if (String.Equals(name, str, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) {
            value = (T)Enum.Parse(typeof(T), name);
            return true;
        }
    }
    return false;
}

অতিরিক্ত নোট:

  • Enum.TryParse। নেট 4 এ অন্তর্ভুক্ত করা হয়েছে এখানে দেখুন http://msdn.microsoft.com/library/dd991876(VS.100).aspx
  • আর একটি পদ্ধতি Enum.Parseহ'ল ব্যর্থ হলে নিক্ষেপ করা ব্যতিক্রমটি সরাসরি মুড়ে ফেলা হবে। কোনও ম্যাচ পাওয়া গেলে এটি আরও দ্রুত হতে পারে তবে এটি যদি না হয় তবে ধীর গতির হতে পারে। আপনি যে ডেটা প্রক্রিয়া করছেন তার উপর নির্ভর করে নেট উন্নতি হতে পারে বা নাও হতে পারে।

সম্পাদনা করুন: শুধু এই একটি ভালভাবে কার্যকর, যা প্রয়োজনীয় তথ্য ক্যাশে দেখা গেছে: http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net- 3-5


আমি ডিফল্ট মান সেট করতে ডিফল্ট (টি) ব্যবহার করার পরামর্শ দিচ্ছি। দেখা যাচ্ছে এটি সমস্ত এনামের জন্য কাজ করবে না। উদাহরণস্বরূপ এনুমের অন্তর্নিহিত প্রকারটি যদি পূর্বনির্ধারিত হয় (টি) সর্বদা 0 হয়, যা এনামের জন্য বৈধ হতে পারে বা নাও পারে।
ড্যানিয়েল বলিঞ্জার

দামিয়েনগের ব্লগে প্রয়োগটি এনট্রিউটের সাথে এনামগুলিকে সমর্থন করে নাFlags
উয়ে কেইম

9

.NET 4.5 এর ভিত্তিতে

নীচে নমুনা কোড

using System;

enum Importance
{
    None,
    Low,
    Medium,
    Critical
}

class Program
{
    static void Main()
    {
    // The input value.
    string value = "Medium";

    // An unitialized variable.
    Importance importance;

    // Call Enum.TryParse method.
    if (Enum.TryParse(value, out importance))
    {
        // We now have an enum type.
        Console.WriteLine(importance == Importance.Medium);
    }
    }
}

তথ্যসূত্র: http://www.dotnetperls.com/enum-parse


4

আমার একটি অপ্টিমাইজড বাস্তবায়ন রয়েছে যা আপনি আনকন্সট্রেন্ডডমেলোডি ব্যবহার করতে পারেন । কার্যকরভাবে এটি কেবল নামের তালিকাই ক্যাশে করছে তবে এটি দুর্দান্ত, দৃ strongly়ভাবে টাইপ করা, সাধারণভাবে সীমাবদ্ধ উপায়ে এটি করছে :)



2

Enum.TryParse বাক্সটির বাইরে এখন নেই। এটি কানেক্টে অনুরোধ করা হয়েছে ( এখনও কোনও এনাম। ট্রাইপার্স নয় ) এবং নেট নেট ৩.৫ এর পরে পরবর্তী কাঠামোর মধ্যে সম্ভাব্য অন্তর্ভুক্তির ইঙ্গিত দিয়ে একটি প্রতিক্রিয়া পেয়েছে। আপনাকে আপাতত প্রস্তাবিত কাজের ক্ষেত্রগুলি প্রয়োগ করতে হবে।


1

ব্যতিক্রম হ্যান্ডলিং এড়ানোর একমাত্র উপায় হ'ল নামকরণ () পদ্ধতিটি ব্যবহার করা এবং আমরা সকলেই জানি যে সাধারণ প্রয়োগের যুক্তির জন্য ব্যতিক্রমগুলি অপব্যবহার করা উচিত নয় :)


4
এটি একমাত্র উপায় নয়। এনাম.আইএসডিফাইনড (..) ব্যবহারকারীর কোডে ব্যতিক্রম হওয়া রোধ করবে।
থোররিন

1

গতিশীলভাবে উত্পন্ন ফাংশন / অভিধানের ক্যাচিং কি অনুমোদিত?

যেহেতু আপনি সময়ের আগে এনামের ধরণটি জানেন না (প্রদর্শিত হবে), তাই প্রথম মৃত্যুদন্ড কার্যকররূপে পরবর্তী মৃত্যুদণ্ড কার্যকর করতে পারে এমন কিছু তৈরি করতে পারে।

আপনি এমনকি এনাম.গেটনামের ফলাফলকে ক্যাশে করতে পারেন ()

আপনি কি সিপিইউ বা মেমোরির জন্য অনুকূলিতকরণের চেষ্টা করছেন? আপনার কি সত্যিই দরকার?


আইপিএ হ'ল সিপিইউ অনুকূলিতকরণ। সম্মত হন যে আমি এটির দামের স্মৃতিতে করতে পারি। তবে এর সমাধানটি আমি খুঁজছি না। ধন্যবাদ
মণীশ বাসন্তানী

0

যেমন অন্যরা ইতিমধ্যে বলেছে, আপনি চেষ্টা ও ক্যাচ ব্যবহার না করেন, আপনার আইসডিফাইন্ড বা গেটনাম ব্যবহার করা দরকার ... এখানে কয়েকটি নমুনা দেওয়া হয়েছে ... সেগুলি মূলত সমস্ত একই, প্রথমটি নালযোগ্য এনামগুলি পরিচালনা করে। আমি দ্বিতীয়টিকে পছন্দ করি কারণ এটি স্ট্রিংগুলিতে এক্সটেনশন, এনামস নয় ... তবে আপনি নিজের ইচ্ছে মতো মিশাতে পারেন!

  • www.objectreferences.net/post/Enum-TryParse- এক্সটেনশন- মেথড.এএসপিএক্স
  • ফ্ল্যাটলাইনারডো.স্পেসেস.লাইভ.com/blog/cns !17124D03A9A052B0!605.entry
  • মিরোনাব্রামসন / ব্লগ / পোস্ট / ২০০৮/০৩/২০১n- অন্যান্য-রূপান্তর- এর জন্য - মিসিং -মোথড- এনিম ট্রাই পার্স.এএসপিএক্স
  • lazyloading.blogspot.com/2008/04/enumtryparse-with-net-35-existance.html

0

ট্রাইপার্স নেই কারণ এনামের ধরণ রানটাইম পর্যন্ত জানা যায়নি। একটি ট্রিপ পার্স যা একই পদ্ধতি অনুসরণ করে যেমন তারিখ বলে ry

আমি এই জাতীয় কিছু করার পরামর্শ দিচ্ছি:

//1 line call to get value
MyEnums enumValue = (Sections)EnumValue(typeof(Sections), myEnumTextValue, MyEnums.SomeEnumDefault);

//Put this somewhere where you can reuse
public static object EnumValue(System.Type enumType, string value, object NotDefinedReplacement)
{
    if (Enum.IsDefined(enumType, value)) {
        return Enum.Parse(enumType, value);
    } else {
        return Enum.Parse(enumType, NotDefinedReplacement);
    }
}

জন্য Tryপদ্ধতি যার ফলাফল মান ধরনের হতে পারে, অথবা যেখানে nullবৈধ ফলাফল হতে পারে (যেমন Dictionary.TryGetValue, which has both such traits), the normal pattern is for a Try` পদ্ধতি ফিরে আসার bool, এবং একটি হিসাবে ফলাফলের পাস outপ্যারামিটার। তাদের জন্য যা রিটার্ন বর্গ ধরনের যেখানে nullএকটি বৈধ ফলে হয় না, একটি ব্যবহার কোন অসুবিধা নেই nullআগমন ব্যর্থতা ইঙ্গিত।
supercat

-1

এনাম ক্লাস (স্ট্রাক্ট?) নিজেই দেখুন। এটিতে একটি পার্স পদ্ধতি আছে তবে আমি ট্রাইপার্স সম্পর্কে নিশ্চিত নই।


আমি এনাম.পার্স (টাইপফ (টিএনম), স্ট্রেইনামভ্যালু) পদ্ধতি সম্পর্কে জানি। যদি strEnumValue বৈধ না হয় তবে এটি আর্গুমেন্টএক্সেপশন ছুড়ে দেয়। ট্রাই পার্সে খুঁজছেন ........
মনিশ

-2

এই পদ্ধতিটি এক ধরণের এনামকে রূপান্তর করবে:

  public static TEnum ToEnum<TEnum>(object EnumValue, TEnum defaultValue)
    {
        if (!Enum.IsDefined(typeof(TEnum), EnumValue))
        {
            Type enumType = Enum.GetUnderlyingType(typeof(TEnum));
            if ( EnumValue.GetType() == enumType )
            {
                string name = Enum.GetName(typeof(HLink.ViewModels.ClaimHeaderViewModel.ClaimStatus), EnumValue);
                if( name != null)
                    return (TEnum)Enum.Parse(typeof(TEnum), name);
                return defaultValue;
            }
        }
        return (TEnum)Enum.Parse(typeof(TEnum), EnumValue.ToString());
    } 

এটি অন্তর্নিহিত প্রকারটি পরীক্ষা করে এবং পার্স করার জন্য এর বিরুদ্ধে নামটি পায়। যদি সবকিছু ব্যর্থ হয় তবে এটি ডিফল্ট মান ফিরে আসবে।


4
এটি কী করছে "এনাম.গেটনাম (টাইপফ (এইচ লিঙ্ক.ভিউমোডেলস। ক্লেইম হাইডারভিউমডেল।ক্লেইম স্ট্যাটাস), এনামভ্যালু)" সম্ভবত আপনার স্থানীয় কোডের উপর কিছুটা নির্ভরতা।
মনীষ বাসন্তানী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.