c# - জেনারিক পদ্ধতি একটি Enum যাও টি সীমাবদ্ধতা তৈরি করুন




generics enums (14)

সি # ≥ 7.3

সি # 7.3 থেকে শুরু (ভিজ্যুয়াল স্টুডিও 2017 ≥ v15.7 এর সাথে উপলব্ধ), এই কোডটি এখন সম্পূর্ণ বৈধ:

public static TEnum Parse<TEnum>(string value)
where TEnum : struct, Enum { ... }

সি # ≤ 7.2

আপনি সীমাবদ্ধ উত্তরাধিকার অপব্যবহার দ্বারা একটি বাস্তব কম্পাইলার enumced enum সীমাবদ্ধতা থাকতে পারে। নিচের কোডটি একই সময়ে একটি class এবং একটি struct উভয়কে নির্দিষ্ট করে:

public abstract class EnumClassUtils<TClass>
where TClass : class
{

    public static TEnum Parse<TEnum>(string value)
    where TEnum : struct, TClass
    {
        return (TEnum) Enum.Parse(typeof(TEnum), value);
    }

}

public class EnumUtils : EnumClassUtils<Enum>
{
}

ব্যবহার:

EnumUtils.Parse<SomeEnum>("value");

দ্রষ্টব্য: এই বিশেষভাবে সি # 5.0 ভাষা স্পেসিফিকেশন বিবৃত করা হয়:

টাইপ পরামিতি S টাইপ প্যারামিটার T এর উপর নির্ভর করে তবে: [...] এটি S -এর জন্য মান টাইপ সীমাবদ্ধতা এবং T এর রেফারেন্স টাইপ সীমাবদ্ধতার জন্য বৈধ। কার্যকরীভাবে এটি সিস্টেম T. Type, System.ValueType, System.Enum, এবং কোনও ইন্টারফেসের প্রকারের T টি সীমাবদ্ধ করে।

আমি Enum.Parse ধারণা যে প্রসারিত একটি ফাংশন নির্মাণ করছি

  • একটি এননাম মান খুঁজে পাওয়া যায় না যদি একটি ডিফল্ট মান পার্স করা যাবে
  • কেস সংবেদনশীল হয়

তাই আমি নিম্নলিখিত লিখেছি:

public static T GetEnumFromString<T>(string value, T defaultValue) where T : Enum
{
    if (string.IsNullOrEmpty(value)) return defaultValue;
    foreach (T item in Enum.GetValues(typeof(T)))
    {
        if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
    }
    return defaultValue;
}

আমি একটি ত্রুটি System.Enum বিশেষ শ্রেণী System.Enum হতে পারে না। System.Enum

ন্যায্য যথেষ্ট, কিন্তু জেনেরিক এনমের অনুমতি দেওয়ার জন্য একটি কার্যকারিতা রয়েছে, নাকি আমি Parse ফাংশনটির অনুকরণ করতে এবং একটি বৈশিষ্ট্য হিসাবে একটি প্রকার পাস করতে যাচ্ছি যা আপনার কোডে কুৎসিত বক্সিং প্রয়োজনীয়তাকে জোরদার করে।

নীচে সব পরামর্শ সম্পাদন করা হয়েছে ব্যাপকভাবে, ধন্যবাদ।

নিষ্পত্তি হয়েছে (আমি কেস অসংবেদকতা বজায় রাখার জন্য লুপটি রেখেছি - এক্সএমএল পার্স করার সময় আমি এটি ব্যবহার করছি)

public static class EnumUtils
{
    public static T ParseEnum<T>(string value, T defaultValue) where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");
        if (string.IsNullOrEmpty(value)) return defaultValue;

        foreach (T item in Enum.GetValues(typeof(T)))
        {
            if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
        }
        return defaultValue;
    }
}

সম্পাদন করুন : (16 ফেব্রুয়ারী 2015) জুলিয়ান লেবস্কুইন সম্প্রতি এমএসআইএল বা এফ # # -তে একটি কম্পাইলার প্রয়োগযোগ্য টাইপ-নিরাপদ জেনেরিক সমাধান পোস্ট করেছেন, যা একটি চেহারা এবং একটি উত্থানের মূল্য। সমাধান বুদবুদ পাতা আপ যদি আমি এই সম্পাদনা মুছে ফেলব।


এই বৈশিষ্ট্য অবশেষে সি # 7.3 সমর্থিত!

নিম্নলিখিত স্নিপেট ( ডটনেট নমুনা থেকে ) এটি ব্যবহার করে দেখায়:

public static Dictionary<int, string> EnumNamedValues<T>() where T : System.Enum
{
    var result = new Dictionary<int, string>();
    var values = Enum.GetValues(typeof(T));

    foreach (int item in values)
        result.Add(item, Enum.GetName(typeof(T), item));
    return result;
}

আপনার সি # প্রোজেক্টে সংস্করণ 7.3 এ আপনার ভাষা সংস্করণ সেট করতে ভুলবেন না।

নীচের মূল উত্তর:

আমি খেলা দেরী করেছি, কিন্তু এটি কিভাবে করা যেতে পারে তা দেখতে একটি চ্যালেঞ্জ হিসাবে আমি এটি গ্রহণ করেছি। এটি C # (বা VB.NET তে সম্ভব নয়, তবে F # এর জন্য স্ক্রোল করুন), তবে MSIL এ এটি সম্ভব । আমি এই সামান্য .... জিনিস

// license: http://www.apache.org/licenses/LICENSE-2.0.html
.assembly MyThing{}
.class public abstract sealed MyThing.Thing
       extends [mscorlib]System.Object
{
  .method public static !!T  GetEnumFromString<valuetype .ctor ([mscorlib]System.Enum) T>(string strValue,
                                                                                          !!T defaultValue) cil managed
  {
    .maxstack  2
    .locals init ([0] !!T temp,
                  [1] !!T return_value,
                  [2] class [mscorlib]System.Collections.IEnumerator enumerator,
                  [3] class [mscorlib]System.IDisposable disposer)
    // if(string.IsNullOrEmpty(strValue)) return defaultValue;
    ldarg strValue
    call bool [mscorlib]System.String::IsNullOrEmpty(string)
    brfalse.s HASVALUE
    br RETURNDEF         // return default it empty

    // foreach (T item in Enum.GetValues(typeof(T)))
  HASVALUE:
    // Enum.GetValues.GetEnumerator()
    ldtoken !!T
    call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
    call class [mscorlib]System.Array [mscorlib]System.Enum::GetValues(class [mscorlib]System.Type)
    callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Array::GetEnumerator() 
    stloc enumerator
    .try
    {
      CONDITION:
        ldloc enumerator
        callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
        brfalse.s LEAVE

      STATEMENTS:
        // T item = (T)Enumerator.Current
        ldloc enumerator
        callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
        unbox.any !!T
        stloc temp
        ldloca.s temp
        constrained. !!T

        // if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
        callvirt instance string [mscorlib]System.Object::ToString()
        callvirt instance string [mscorlib]System.String::ToLower()
        ldarg strValue
        callvirt instance string [mscorlib]System.String::Trim()
        callvirt instance string [mscorlib]System.String::ToLower()
        callvirt instance bool [mscorlib]System.String::Equals(string)
        brfalse.s CONDITION
        ldloc temp
        stloc return_value
        leave.s RETURNVAL

      LEAVE:
        leave.s RETURNDEF
    }
    finally
    {
        // ArrayList's Enumerator may or may not inherit from IDisposable
        ldloc enumerator
        isinst [mscorlib]System.IDisposable
        stloc.s disposer
        ldloc.s disposer
        ldnull
        ceq
        brtrue.s LEAVEFINALLY
        ldloc.s disposer
        callvirt instance void [mscorlib]System.IDisposable::Dispose()
      LEAVEFINALLY:
        endfinally
    }

  RETURNDEF:
    ldarg defaultValue
    stloc return_value

  RETURNVAL:
    ldloc return_value
    ret
  }
} 

যা এমন একটি ফাংশন তৈরি করে যা এটির মত দেখতে হবে , যদি এটি বৈধ C #:

T GetEnumFromString<T>(string valueString, T defaultValue) where T : Enum

তারপর নিম্নলিখিত সি # কোড দিয়ে:

using MyThing;
// stuff...
private enum MyEnum { Yes, No, Okay }
static void Main(string[] args)
{
    Thing.GetEnumFromString("No", MyEnum.Yes); // returns MyEnum.No
    Thing.GetEnumFromString("Invalid", MyEnum.Okay);  // returns MyEnum.Okay
    Thing.GetEnumFromString("AnotherInvalid", 0); // compiler error, not an Enum
}

দুর্ভাগ্যবশত, এর অর্থ হল সি # এর পরিবর্তে MSIL- এ লেখা আপনার কোডের এই অংশটি থাকা, কেবলমাত্র যোগ করা সুবিধাটি হচ্ছে যে আপনি এই পদ্ধতিটি System.Enum দ্বারা সীমাবদ্ধ করতে পারবেন। System.Enum । এটি একটি bummer ধরনের, কারণ এটি একটি পৃথক সমাবেশে সংকলিত পায়। যাইহোক, এর অর্থ এই নয় যে আপনাকে এভাবে স্থাপন করতে হবে।

লাইন মুছে ফেলার মাধ্যমে। .assembly MyThing{} এবং নিম্নরূপ:

ilasm.exe /DLL /OUTPUT=MyThing.netmodule

আপনি একটি সমাবেশ পরিবর্তে একটি নেটমডিউল পেতে।

দুর্ভাগ্যবশত, VS2010 (এবং পূর্বে, সম্ভবতঃ) নেটমডিউল রেফারেন্সগুলি যোগ করার জন্য সমর্থন করে না, যার মানে আপনি ডিবাগিংয়ের সময় 2 আলাদা সংবিধানগুলিতে এটি ছেড়ে দিতে চান। আপনার সমাবেশের অংশ হিসাবে আপনি তাদের যুক্ত করতে একমাত্র উপায় csc.exe চালানো হবে /addmodule:{files} ব্যবহার করে /addmodule:{files} কমান্ড লাইন আর্গুমেন্ট। এটি একটি MSBuild স্ক্রিপ্টে খুব বেদনাদায়ক হবে না। অবশ্যই, যদি আপনি সাহসী বা বোকা হন, তবে আপনি প্রতিটি সময় নিজে নিজে সিএসসি চালাতে পারেন। এবং একাধিক সমাহারগুলি অ্যাক্সেস প্রয়োজন হিসাবে এটি অবশ্যই আরো জটিল পায়।

সুতরাং, এটা করতে পারেন নেট। এটা অতিরিক্ত প্রচেষ্টা মূল্য? উম, আচ্ছা, আমি অনুমান করছি যে আপনি ওকে সিদ্ধান্ত নেবেন।

বিকল্প হিসাবে F # সমাধান

অতিরিক্ত ক্রেডিট: এটি দেখায় যে enum ছাড়া কমপক্ষে অন্য একটি। নেট ভাষাতে enum উপর একটি সাধারণ সীমাবদ্ধতা সম্ভব: F #।

type MyThing =
    static member GetEnumFromString<'T when 'T :> Enum> str defaultValue: 'T =
        /// protect for null (only required in interop with C#)
        let str = if isNull str then String.Empty else str

        Enum.GetValues(typedefof<'T>)
        |> Seq.cast<_>
        |> Seq.tryFind(fun v -> String.Compare(v.ToString(), str.Trim(), true) = 0)
        |> function Some x -> x | None -> defaultValue

এটি সম্পূর্ণরূপে বজায় রাখা সহজ, কারণ এটি সম্পূর্ণ ভিজ্যুয়াল স্টুডিও আইডিই সমর্থন সহ একটি সুপরিচিত ভাষা, তবে আপনার এখনও এটির জন্য আপনার সমাধানটিতে একটি পৃথক প্রকল্প প্রয়োজন। যাইহোক, এটি স্বাভাবিকভাবেই বিভিন্ন আইএল তৈরি করে (কোডটি খুব ভিন্ন) এবং এটি FSharp.Core লাইব্রেরিতে নির্ভর করে, যা অন্য যেকোন বহিরাগত লাইব্রেরির মতোই আপনার বিতরণের অংশ হতে পারে।

এখানে আপনি কীভাবে এটি ব্যবহার করতে পারেন (মূলত MSIL সমাধান হিসাবে একই), এবং এটি অন্যথায় সমার্থক structs এ সঠিকভাবে ব্যর্থ হয় তা দেখানোর জন্য:

// works, result is inferred to have type StringComparison
var result = MyThing.GetEnumFromString("OrdinalIgnoreCase", StringComparison.Ordinal);
// type restriction is recognized by C#, this fails at compile time
var result = MyThing.GetEnumFromString("OrdinalIgnoreCase", 42);

আপনি ক্লাসের জন্য একটি স্ট্যাটিক কন্সট্রাকটর সংজ্ঞায়িত করতে পারেন যা টাইপ টি টাইপ একটি enum এবং যদি এটি না হয় তবে একটি ব্যতিক্রম নিক্ষেপ করে। জেফেরি রিচার্ট তার বই সিএলআর মাধ্যমে সি # এ উল্লেখ পদ্ধতি।

internal sealed class GenericTypeThatRequiresAnEnum<T> {
    static GenericTypeThatRequiresAnEnum() {
        if (!typeof(T).IsEnum) {
        throw new ArgumentException("T must be an enumerated type");
        }
    }
}

তারপর পার্স পদ্ধতিতে, আপনি স্ট্রিং থেকে enum রূপান্তর করতে Enum.Parse (typeof (টি), ইনপুট, সত্য) ব্যবহার করতে পারেন। শেষ সত্য পরামিতি ইনপুট ক্ষেত্রে উপেক্ষা করার জন্য হয়।


আমি to get integer value from enum একটি এক্সটেনশন পদ্ধতি তৈরি পদ্ধতি পদ্ধতি বাস্তবায়ন তাকান

public static int ToInt<T>(this T soure) where T : IConvertible//enum
{
    if (typeof(T).IsEnum)
    {
        return (int) (IConvertible)soure;// the tricky part
    }
    //else
    //    throw new ArgumentException("T must be an enumerated type");
    return soure.ToInt32(CultureInfo.CurrentCulture);
}

এই ব্যবহার

MemberStatusEnum.Activated.ToInt()// using extension Method
(int) MemberStatusEnum.Activated //the ordinary way

আমি আইটি ব্যবহার করে ক্রিস্টোফার কারেনস এর সমাধান পছন্দ করি, কিন্তু যারা তাদের বিল্ড প্রসেসে MSIL সহ চতুর ব্যবসায়ের সাথে মোকাবিলা করতে চায় না তাদের জন্য আমি সি # এ একই কাজ লিখেছিলাম।

যদিও আপনি জেনারিক সীমাবদ্ধতা ব্যবহার করতে পারেন না তবে দয়া করে মনে রাখবেন যে where T : Enum কারণ Enum বিশেষ ধরনের। তাই আমি জেনেরিক টাইপ সত্যিই enum হয় কিনা তা পরীক্ষা করতে হবে।

আমার ফাংশন হল:

public static T GetEnumFromString<T>(string strValue, T defaultValue)
{
    // Check if it realy enum at runtime 
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Method GetEnumFromString can be used with enums only");

    if (!string.IsNullOrEmpty(strValue))
    {
        IEnumerator enumerator = Enum.GetValues(typeof(T)).GetEnumerator();
        while (enumerator.MoveNext())
        {
            T temp = (T)enumerator.Current;
            if (temp.ToString().ToLower().Equals(strValue.Trim().ToLower()))
                return temp;
        }
    }

    return defaultValue;
}

আমি উইভিকের সমাধানটি ইউটিলিটি ক্লাসে অন্তর্ভুক্ত করেছি যা আপনি পুনঃব্যবহার করতে পারেন। অনুগ্রহ করে নোট করুন যে আপনি এখনও আপনার টাইপের টাইপ সীমাবদ্ধতা "যেখানে টি: struct, IConvertible" নির্ধারণ করতে হবে।

using System;

internal static class EnumEnforcer
{
    /// <summary>
    /// Makes sure that generic input parameter is of an enumerated type.
    /// </summary>
    /// <typeparam name="T">Type that should be checked.</typeparam>
    /// <param name="typeParameterName">Name of the type parameter.</param>
    /// <param name="methodName">Name of the method which accepted the parameter.</param>
    public static void EnforceIsEnum<T>(string typeParameterName, string methodName)
        where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            string message = string.Format(
                "Generic parameter {0} in {1} method forces an enumerated type. Make sure your type parameter {0} is an enum.",
                typeParameterName,
                methodName);

            throw new ArgumentException(message);
        }
    }

    /// <summary>
    /// Makes sure that generic input parameter is of an enumerated type.
    /// </summary>
    /// <typeparam name="T">Type that should be checked.</typeparam>
    /// <param name="typeParameterName">Name of the type parameter.</param>
    /// <param name="methodName">Name of the method which accepted the parameter.</param>
    /// <param name="inputParameterName">Name of the input parameter of this page.</param>
    public static void EnforceIsEnum<T>(string typeParameterName, string methodName, string inputParameterName)
        where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            string message = string.Format(
                "Generic parameter {0} in {1} method forces an enumerated type. Make sure your input parameter {2} is of correct type.",
                typeParameterName,
                methodName,
                inputParameterName);

            throw new ArgumentException(message);
        }
    }

    /// <summary>
    /// Makes sure that generic input parameter is of an enumerated type.
    /// </summary>
    /// <typeparam name="T">Type that should be checked.</typeparam>
    /// <param name="exceptionMessage">Message to show in case T is not an enum.</param>
    public static void EnforceIsEnum<T>(string exceptionMessage)
        where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException(exceptionMessage);
        }
    }
}

আমি নির্দিষ্ট প্রয়োজন আছে যেখানে enum মান সঙ্গে যুক্ত টেক্সট সঙ্গে enum ব্যবহার করতে হবে। উদাহরণস্বরূপ, যখন আমি ত্রুটি টাইপ নির্দিষ্ট করার জন্য enum ব্যবহার করি তখন এটি ত্রুটি বিশদের বর্ণনা দিতে হবে।

public static class XmlEnumExtension
{
    public static string ReadXmlEnumAttribute(this Enum value)
    {
        if (value == null) throw new ArgumentNullException("value");
        var attribs = (XmlEnumAttribute[]) value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof (XmlEnumAttribute), true);
        return attribs.Length > 0 ? attribs[0].Name : value.ToString();
    }

    public static T ParseXmlEnumAttribute<T>(this string str)
    {
        foreach (T item in Enum.GetValues(typeof(T)))
        {
            var attribs = (XmlEnumAttribute[])item.GetType().GetField(item.ToString()).GetCustomAttributes(typeof(XmlEnumAttribute), true);
            if(attribs.Length > 0 && attribs[0].Name.Equals(str)) return item;
        }
        return (T)Enum.Parse(typeof(T), str, true);
    }
}

public enum MyEnum
{
    [XmlEnum("First Value")]
    One,
    [XmlEnum("Second Value")]
    Two,
    Three
}

 static void Main()
 {
    // Parsing from XmlEnum attribute
    var str = "Second Value";
    var me = str.ParseXmlEnumAttribute<MyEnum>();
    System.Console.WriteLine(me.ReadXmlEnumAttribute());
    // Parsing without XmlEnum
    str = "Three";
    me = str.ParseXmlEnumAttribute<MyEnum>();
    System.Console.WriteLine(me.ReadXmlEnumAttribute());
    me = MyEnum.One;
    System.Console.WriteLine(me.ReadXmlEnumAttribute());
}

আমি সবসময় এই পছন্দ (আপনি উপযুক্ত হিসাবে সংশোধন করতে পারে):

public static IEnumerable<TEnum> GetEnumValues()
{
  Type enumType = typeof(TEnum);

  if(!enumType.IsEnum)
    throw new ArgumentException("Type argument must be Enum type");

  Array enumValues = Enum.GetValues(enumType);
  return enumValues.Cast<TEnum>();
}

এই সহায়ক হয় আশা করি:

public static TValue ParseEnum<TValue>(string value, TValue defaultValue)
                  where TValue : struct // enum 
{
      try
      {
            if (String.IsNullOrEmpty(value))
                  return defaultValue;
            return (TValue)Enum.Parse(typeof (TValue), value);
      }
      catch(Exception ex)
      {
            return defaultValue;
      }
}

এটিও বিবেচনা করা উচিত যে যেহেতু Enum সীমাবদ্ধতা ব্যবহার করে C # 7.3 প্রকাশ করার পরে অতিরিক্ত চেক এবং স্টাফ না করে আউট-দ্য-বক্স সমর্থিত।

তাই এগিয়ে যান এবং আপনি আপনার প্রকল্পের ভাষা সংস্করণটি C # 7.3 এ পরিবর্তন করেছেন, নিম্নলিখিত কোড পুরোপুরি সূক্ষ্ম কাজ করতে যাচ্ছে:

    private static T GetEnumFromString<T>(string value, T defaultValue) where T : Enum
    {
        // Your code goes here...
    }

যদি আপনি ভাষা সংস্করণটি C # 7.3 এ পরিবর্তন করতে না পারেন তবে নিম্নলিখিত স্ক্রিনশটটি দেখুন:

সম্পাদনা 1 - প্রয়োজনীয় ভিজ্যুয়াল স্টুডিও সংস্করণ এবং ReSharper বিবেচনা

ভিসুয়াল স্টুডিওর জন্য নতুন সিনট্যাক্সটি চিনতে আপনার কমপক্ষে সংস্করণ 15.7 প্রয়োজন। মাইক্রোসফটের রিলিজ নোটগুলিতেও উল্লেখ করা যায়, ভিজ্যুয়াল স্টুডিও 2017 15.7 রিলিজ নোট দেখুন । এই বৈধ প্রশ্নের ইঙ্গিত দেওয়ার জন্য ধন্যবাদ @ মোহাম্মাদ ইলিশশাফ।

Pls এছাড়াও মনে রাখবেন যে আমার ক্ষেত্রে ReSharper 2018.1 এই EDIT লেখার জন্য এখনও C # 7.3 সমর্থন করে না। ReSharper সক্রিয় করে এটি Enum সীমাবদ্ধতাকে হাইলাইট করে বলে একটি ত্রুটি হিসাবে আমাকে 'System.Array', 'System.Delelegate', 'System.Enum', 'System.valueType', 'object' টাইপ পরামিতি সীমাবদ্ধতা হিসাবে ব্যবহার করতে পারে না । ReSharper পদ্ধতির টাইপ প্যারামিটার টি 'Enum' সীমাবদ্ধতা সরানোর জন্য একটি দ্রুত ফিক্স হিসাবে সুপারিশ

যাইহোক, যদি আপনি রিসার্পারটিকে অস্থায়ীভাবে সরঞ্জাম -> বিকল্পসমূহ -> রিশারপার আল্টিমেট -> জেনারেলের অধীনে বন্ধ করেন তবে আপনি দেখতে পাবেন যে সিনট্যাক্স পুরোপুরি জরিমানা যা আপনি VS 15.7 বা তার বেশি এবং C # 7.3 বা তারপরে ব্যবহার করেন।


যেহেতু IConvertible টাইপ IConvertible ইন্টারফেস প্রয়োগ করে, একটি ভাল বাস্তবায়ন এমন কিছু হওয়া উচিত:

public T GetEnumFromString<T>(string value) where T : struct, IConvertible
{
   if (!typeof(T).IsEnum) 
   {
      throw new ArgumentException("T must be an enumerated type");
   }

   //...
}

এটি এখনও IConvertible বাস্তবায়ন মান ধরনের পাস করার অনুমতি IConvertible । সম্ভাবনা যদিও বিরল।


সম্পাদন করা

প্রশ্নটি এখন জালিয়েন লেবোস্কিনের চমত্কারভাবে জবাব দিয়েছে । আমি TryParse এবং ParseOrDefault যোগ করার সময়, ignoreCase , defaultValue এবং ঐচ্ছিক আর্গুমেন্টগুলির সাথে তার উত্তর প্রসারিত করতে চাই।

public abstract class ConstrainedEnumParser<TClass> where TClass : class
// value type constraint S ("TEnum") depends on reference type T ("TClass") [and on struct]
{
    // internal constructor, to prevent this class from being inherited outside this code
    internal ConstrainedEnumParser() {}
    // Parse using pragmatic/adhoc hard cast:
    //  - struct + class = enum
    //  - 'guaranteed' call from derived <System.Enum>-constrained type EnumUtils
    public static TEnum Parse<TEnum>(string value, bool ignoreCase = false) where TEnum : struct, TClass
    {
        return (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase);
    }
    public static bool TryParse<TEnum>(string value, out TEnum result, bool ignoreCase = false, TEnum defaultValue = default(TEnum)) where TEnum : struct, TClass // value type constraint S depending on T
    {
        var didParse = Enum.TryParse(value, ignoreCase, out result);
        if (didParse == false)
        {
            result = defaultValue;
        }
        return didParse;
    }
    public static TEnum ParseOrDefault<TEnum>(string value, bool ignoreCase = false, TEnum defaultValue = default(TEnum)) where TEnum : struct, TClass // value type constraint S depending on T
    {
        if (string.IsNullOrEmpty(value)) { return defaultValue; }
        TEnum result;
        if (Enum.TryParse(value, ignoreCase, out result)) { return result; }
        return defaultValue;
    }
}

public class EnumUtils: ConstrainedEnumParser<System.Enum>
// reference type constraint to any <System.Enum>
{
    // call to parse will then contain constraint to specific <System.Enum>-class
}

ব্যবহারের উদাহরণ:

WeekDay parsedDayOrArgumentException = EnumUtils.Parse<WeekDay>("monday", ignoreCase:true);
WeekDay parsedDayOrDefault;
bool didParse = EnumUtils.TryParse<WeekDay>("clubs", out parsedDayOrDefault, ignoreCase:true);
parsedDayOrDefault = EnumUtils.ParseOrDefault<WeekDay>("friday", ignoreCase:true, defaultValue:WeekDay.Sunday);

পুরাতন

মন্তব্য এবং 'নতুন' share ব্যবহার করে share আমার পুরনো উন্নতি:

  • ব্যবহারকারীদের জন্য স্বচ্ছতার জন্য TEnum ব্যবহার করুন
  • অতিরিক্ত সীমাবদ্ধতা পরীক্ষার জন্য আরো ইন্টারফেস-সীমাবদ্ধতা যোগ করুন
  • TryParse হ্যান্ডেল ignoreCase করা বর্তমান পরামিতি (VS2010 / নেট 4 এ উপস্থাপিত)
  • বিকল্পভাবে জেনেরিক default মান ব্যবহার করুন (VS2005 / .Net 2 এ উপস্থাপিত)
  • পূর্বনির্ধারিত আর্গুমেন্টগুলি ব্যবহার করুন (VS2010 / .Net 4 এ উপস্থাপিত) ডিফল্ট মানগুলির সাথে, ডিফল্ট ভ্যালু এবং ignoreCase

ফলে:

public static class EnumUtils
{
    public static TEnum ParseEnum<TEnum>(this string value,
                                         bool ignoreCase = true,
                                         TEnum defaultValue = default(TEnum))
        where TEnum : struct,  IComparable, IFormattable, IConvertible
    {
        if ( ! typeof(TEnum).IsEnum) { throw new ArgumentException("TEnum must be an enumerated type"); }
        if (string.IsNullOrEmpty(value)) { return defaultValue; }
        TEnum lResult;
        if (Enum.TryParse(value, ignoreCase, out lResult)) { return lResult; }
        return defaultValue;
    }
}

আগে অন্যান্য উত্তর বিবৃত হিসাবে; যদিও এটি উৎস-কোডে প্রকাশ করা যাবে না এটি আসলে আইএল লেভেলে করা যেতে পারে। @ ক্রিসটোফার কারেনস answer দেখায় কিভাবে আইএল এর সাথে কাজ করে।

সঙ্গে Fody s যোগ-ইন ExtraConstraints.Fody সেখানে একটি খুব সহজ ভাবে, বিল্ড-সাধনী দ্বারা প্রয়োগকরণ সঙ্গে সম্পূর্ণ, এই অর্জন আছে। শুধু আপনার প্রকল্পে তাদের ngetget প্যাকেজ ( Fody, ExtraConstraints.Fody) যোগ করুন এবং নিম্নরূপ সীমাবদ্ধতা যোগ করুন (ExtraConstraints এর পাঠ্য থেকে উদ্ধৃতি):

public void MethodWithEnumConstraint<[EnumConstraint] T>() {...}

public void MethodWithTypeEnumConstraint<[EnumConstraint(typeof(ConsoleColor))] T>() {...}

এবং Fody উপস্থিত IL চাপ উপস্থিত হতে হবে। এছাড়াও প্রতিনিধিদের সীমাবদ্ধ অতিরিক্ত বৈশিষ্ট্য নোট:

public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
{...}

public void MethodWithTypeDelegateConstraint<[DelegateConstraint(typeof(Func<int>))] T> ()
{...}

Enums সম্পর্কিত, আপনি খুব আকর্ষণীয় Enums.NET নোট নিতে চাইতে পারেন ।


পরে সরাসরি কাস্টিং ব্যবহার করা ঠিক আছে, আমি মনে করি আপনি System.Enumপ্রয়োজন অনুসারে আপনার পদ্ধতিতে বেস ক্লাসটি ব্যবহার করতে পারেন । আপনি শুধু সাবধানে টাইপ পরামিতি প্রতিস্থাপন করতে হবে। সুতরাং পদ্ধতি বাস্তবায়ন ভালো হবে:

public static class EnumUtils
{
    public static Enum GetEnumFromString(string value, Enum defaultValue)
    {
        if (string.IsNullOrEmpty(value)) return defaultValue;
        foreach (Enum item in Enum.GetValues(defaultValue.GetType()))
        {
            if (item.ToString().ToLower().Equals(value.Trim().ToLower())) return item;
        }
        return defaultValue;
    }
}

তারপর আপনি এটি ব্যবহার করতে পারেন:

var parsedOutput = (YourEnum)EnumUtils.GetEnumFromString(someString, YourEnum.DefaultValue);




generic-constraints