একটি এনুমকে টি সীমাবদ্ধ করে জেনেরিক পদ্ধতি তৈরি করুন


1187

আমি 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

যথেষ্ট উপযুক্ত, তবে জেনেরিক এনুমকে অনুমতি দেওয়ার মতো কোনও 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;
    }
}

সম্পাদনা: (১ Feb ফেব্রুয়ারী ২০১৫) জুলিয়েন লেবোসকাইন সম্প্রতি এমএসআইএল বা এফ # তে একটি সংকলক প্রয়োগকারী টাইপ-নিরাপদ জেনেরিক সমাধান পোস্ট করেছেন , যা দেখতে ভাল এবং একটি উচ্চ মূল্যবান। সমাধানটি পৃষ্ঠাটিতে আরও বুদবুদ হলে আমি এই সম্পাদনাটি সরিয়ে ফেলব।


10
হতে পারে আপনার ToLower () এর পরিবর্তে ToUpperInvariant () ব্যবহার করা উচিত ...
ম্যাক্স গ্যালকিন

31
@ শিম্মি: আপনি এক্সটেনশন পদ্ধতিতে কোনও মান ধরণের পাস করার সাথে সাথে আপনি এর অনুলিপি নিয়ে কাজ করছেন, যাতে আপনি এর অবস্থা পরিবর্তন করতে পারবেন না।
গারো ইয়ারিয়াজারিয়ান

4
এটি একটি পুরানো থ্রেড জানুন, তারা জিনিসগুলি পরিবর্তন করেছেন কিনা তা জানেন না, তবে এক্সটেনশন পদ্ধতিগুলি মান ধরণের জন্য ঠিকঠাক কাজ করে, নিশ্চিত যে তারা সর্বদা যথাযথভাবে অর্থ বোধ করতে পারে না, তবে আমি "পাবলিক স্ট্যাটিক টাইমস্প্যান সেকেন্ডস (এটি ইন্টার এক্স) ব্যবহার করেছি" { "ওয়েট.ফোর (5.সেকেন্ডস ()) ..." এর সিনট্যাক্স সক্ষম করতে টাইমস্প্যান.ফর্মসেকেন্ডস (এক্স);} "ফিরিয়ে দিন
জেনস

6
উপলব্ধি করুন যে এটি প্রশ্নের অংশ ছিল না, তবে আপনি স্ট্রিংকম্পায়ারেন্সের সাথে স্ট্রিংএকুইকেলস ব্যবহার করে আপনার ফোরচ লুপ লজিকটি উন্নত করতে পারেন nআভিনভারেন্টক্ল্যাচারআইগনরেস কেস
ফায়ারস্ট্র্যান্ড

উত্তর:


1005

যেহেতু Enumপ্রকারটি 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। সম্ভাবনা যদিও বিরল।


2
জেনারিকগুলি .NET 2.0 থেকে উপলব্ধ। সুতরাং তারা vb 2005 এও উপলব্ধ।
বিবেক

46
ঠিক আছে, তবে এটি আরও জটিল করে তুলুন, যদি আপনি এই পথটিতে যেতে চান ... "ক্লাসের টেস্টক্লাস <T> ব্যবহার করুন যেখানে টি: স্ট্রাক্ট, আইকনপমারেবল, আইফোর্মেটেবল, আইকনভারটেবল"
রিকার্ডো

106
আর একটি পরামর্শ হ'ল জেনেরিক ধরণটি সনাক্তকারী টিএনম দিয়ে সংজ্ঞায়িত করা। সুতরাং: সর্বজনীন টেনাম গেটইনম ফ্রম স্ট্রিং <TEnum> (স্ট্রিংয়ের মান) যেখানে টেনাম: স্ট্রাক্ট, আইকনভার্টেবল, আইসিম্পারিবল, আইফোর্মেটেবল {}
লিসা

11
আপনি অন্যান্য ইন্টারফেসগুলি অন্তর্ভুক্ত করে খুব বেশি লাভ করতে পারবেন না কারণ প্রায় সমস্ত বিল্ট-ইন মান ধরণের সমস্ত ইন্টারফেস প্রয়োগ করে। এটি জেনেরিক এক্সটেনশন পদ্ধতির প্রতিবন্ধকতার জন্য বিশেষত সত্য, যা এনামগুলিতে পরিচালনা করার জন্য অত্যন্ত কার্যকর, এই এক্সটেনশন পদ্ধতিগুলি একটি ভাইরাসের মতো যা আপনার সমস্ত বস্তুকে সংক্রামিত করে। আইকনভারটেবল এটি কমপক্ষে কিছুটা কমিয়ে দেয়।
রাশিবিশপ

2
@ সামিয়াম: যখন আপনি পোস্ট করেছিলেন, তখন এই থ্রেডটি ছিল, সাড়ে years বছর বয়সী এবং আপনি সঠিক ছিলেন, কোনও উত্তরের জন্য কোনও সংকলিত-সময় পরীক্ষা করা হয়নি। তারপরে মাত্র 3 দিন পরে, 6 বছর পরে, আপনি আপনার ইচ্ছাকে পেয়েছেন - নীচে জুলিয়েন লেবোসকুইনের পোস্টের উপায়টি দেখুন।
ডেভিড আই ম্যাকিনটোস

662

এই বৈশিষ্ট্যটি শেষ পর্যন্ত সি # 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 সংস্করণে সেট করা নিশ্চিত করুন।


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

আমি খেলায় দেরি করেছি, তবে কীভাবে এটি করা যায় তা দেখার জন্য আমি এটিকে চ্যালেঞ্জ হিসাবে নিয়েছিলাম। এটি সি # (বা ভিবি.এনইটি তে সম্ভব নয়, তবে এফ # এর জন্য স্ক্রোল করুন) তবে এমএসআইএল-এ এটি সম্ভব । আমি এই ছোট্ট .... জিনিস লিখেছি

// 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
  }
} 

কোনটি ফাংশন যা উত্পন্ন হবে ভালো চেহারা, যদি এটা ছিল বৈধ সি #:

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
}

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

লাইনটি সরিয়ে এবং নীচে .assembly MyThing{}ইলাসমকে অনুরোধ করে:

ilasm.exe /DLL /OUTPUT=MyThing.netmodule

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

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

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


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

অতিরিক্ত ক্রেডিট: দেখা গেছে যে enumএমএসআইএল: এফ ছাড়াও কমপক্ষে অন্য একটি। নেট ভাষায় জেনেরিক বিধিনিষেধের সম্ভাবনা রয়েছে।

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

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

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

// 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);

67
হ্যাঁ, খুব হার্ডকোর আমি এমন একজন যে আইএল কোড করতে পারেন জন্য পরম শ্রদ্ধা আছে এবং একটি স্তর যা আমরা অনেকেই এখনো অ্যাপ্লিকেশন, ব্যবসার নীতি, UI 'তে এর, কম্পোনেন্ট লাইব্রেরি, ইত্যাদি অধীনে নিম্ন স্তরের হচ্ছে দেখুন - কিভাবে জানি বৈশিষ্ট্য উচ্চতর ভাষা পর্যায়ে সমর্থিত ।
টনিজি 1

13
আমি যা জানতে চাই তা হ'ল সি # টিম কেন এখনও এটিকে অনুমতি দেয় নি, কারণ এটি এমএসআইএল এরই মধ্যে সমর্থিত।
MgSam

25
@ এমজিস্যাম - এরিক লিপার্ট থেকে :There's no particularly unusual reason why not; we have lots of other things to do, limited budgets, and this one has never made it past the "wouldn't this be nice?" discussion in the language design team.
ক্রিস্টোফার কারেনস

5
@LordofScripts: আমার মনে হয় কারণ যে যেহেতু একটি শ্রেণী যেটি একটি সীমাবদ্ধ নয় Tকরার System.Enumসঙ্গে সব কিছু করার পারব না Tযে মানুষ আশা করতে পারে, সি # লেখক মূর্ত সেগুলিও এর সাথে সাথে এটা পুরাপুরি নিষেধ করতে পারে। আমি সিদ্ধান্তটিকে দুর্ভাগ্য বলে বিবেচনা করি, যেহেতু এটি সি # কোনও বিশেষ নিয়ন্ত্রণের System.Enumসীমাবদ্ধতাগুলি কেবল উপেক্ষা করেছিল , তাই কোনও HasAnyFlags<T>(this T it, T other)এক্সটেনশন পদ্ধতিটি লেখা সম্ভব ছিল Enum.HasFlag(Enum)যা তাত্পর্যপূর্ণতার চেয়ে দ্রুততর ছিল এবং কোনটি তার যুক্তিগুলি টাইপ-চেক করেছিল।
ক্যাট

9
আমি মনে করি না যে আমি কখনও এমন একটি প্রকল্প করেছি যেখানে আমার এখানে শেষ হয়নি। সি # 6 110% সিনট্যাকটিক চিনি এবং এইটি পাওয়া যায় নি? বাজে কথা কাটা।
মাইকেল ব্ল্যাকবার্ন

214

সি # ≥ 7.3

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

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

সি # ≤ 7.2

সীমাবদ্ধতার উত্তরাধিকারকে অপব্যবহার করে আপনার কাছে একটি বাস্তব সংকলক প্রযোজ্য এনাম সীমাবদ্ধতা থাকতে পারে। নিম্নলিখিত কোড দুটি 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 ভাষার স্পেসিফিকেশনে বর্ণিত হয়েছে:

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


7
@ ডেভিডআই.এমসিআইনটোস EnumClassUtils<System.Enum>টি কোনও System.Enumএবং যে কোনও উদ্ভূত প্রকারের মধ্যে টি সীমাবদ্ধ করতে যথেষ্ট । structউপর Parseতারপর এটি একটি বাস্তব enum টাইপ আরও নিষিদ্ধ। আপনাকে Enumকিছু সময় সীমাবদ্ধ করতে হবে। এটি করতে, আপনার ক্লাসটি বাসাতে হবে। Gist.github.com/MrJul/7da12f5f2d6c69f03d79
জুলিয়েন লেবোসকাইন

7
কেবল পরিষ্কারভাবে বলতে গেলে, আমার মন্তব্যটি "সুখকর নয়" আপনার সমাধান সম্পর্কে কোনও মন্তব্য ছিল না - এটি সত্যই একটি সুন্দর হ্যাক। কেবল "আনন্দদায়ক নয়" যা এমএস আমাদেরকে এইরকম সংহত হ্যাক ব্যবহার করতে বাধ্য করে।
ডেভিড আই ম্যাকিনটোস

2
এক্সটেনশন পদ্ধতির জন্যও এটি ব্যবহার করার মতো কোনও উপায় আছে?
মর্ড জুবের

3
কি where TClass : classএখানে বাধ্যতা লাভ কি?
tsemer

2
@ ত্রিংকিওenum DefinitelyNotAnInt : byte { Realize, That, I, Am, Not, An, Int } enum AlsoNotAnInt : long { Well, Bummer }
এম স্ট্র্যাম

30

সম্পাদন করা

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

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);

পুরাতন

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

  • ব্যবহারকারীদের TEnumজন্য স্বচ্ছতার জন্য ব্যবহার করুন
  • অতিরিক্ত সীমাবদ্ধতা-পরীক্ষার জন্য আরও ইন্টারফেস-সীমাবদ্ধতা যুক্ত করুন
  • বিদ্যমান প্যারামিটারটি TryParseহ্যান্ডেল করা যাক ignoreCase(ভিএস 2010 /। নেট 4 এ প্রবর্তিত)
  • allyচ্ছিকভাবে জেনেরিক defaultমানটি (VS2005 /। নেট 2 তে প্রবর্তিত) ব্যবহার করুন
  • al চ্ছিক যুক্তি ব্যবহার করুন জন্য defaultValueএবং এর জন্য ডিফল্ট মান সহ alচ্ছিক (VS2010 /। নেট 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;
    }
}

18

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

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

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


1
এটি জেনেরিক ক্লাসগুলির জন্য একটি ভাল বিকল্প - তবে অবশ্যই এটি জেনেরিক পদ্ধতিতে সহায়তা করে না।
ম্যাকগার্নাগল

এছাড়াও, এটি সংকলনের সময় কার্যকর করা হয় না, আপনি কেবল তখনই জানতেন Enum Tযে কনস্ট্রাক্টর মৃত্যুদন্ড কার্যকর করার সময় আপনি একটি অ সরবরাহ করেছিলেন। যদিও এটি ইনস্ট্যান্ট কনস্ট্রাক্টরের অপেক্ষা অপেক্ষা অনেক সুন্দর।
জুন

15

এটিও বিবেচনা করা উচিত যে যেহেতু এনাম সীমাবদ্ধতাগুলি ব্যবহার করে সি # 7.3 প্রকাশ হ'ল অতিরিক্ত চেকিং এবং স্টাফ না করে বাইরের বাইরে সমর্থনযোগ্য।

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

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

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

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

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

প্লিজ আরও নোট করুন যে আমার ক্ষেত্রে এই শেয়ারটি 2018.1 হিসাবে রিশার্পার এখনও সি # 7.3 সমর্থন করে না। রিশার্পারকে সক্রিয় করা এটি এনাম বাধাটিকে একটি ত্রুটি হিসাবে হাইলাইট করে আমাকে 'সিস্টেম.আর্রে', 'সিস্টেম.ডেলিগেট', 'সিস্টেম.ইনুম', 'সিস্টেম.ভালিউটাইপ', 'অবজেক্ট' টাইপ প্যারামিটার সীমাবদ্ধতা হিসাবে ব্যবহার করতে পারে না বলে জানিয়েছে । রিশার্পার পদ্ধতিটির পরামিতি টাইপের টাইপ ' এনাম ' সরিয়ে দেওয়ার দ্রুত সমাধান হিসাবে পরামর্শ দেয়

তবে, আপনি যদি সরঞ্জামগুলি -> বিকল্পগুলি -> রিশ্যার আলটিমেট -> জেনারেলের অধীনে রিসার্পারকে অস্থায়ীভাবে বন্ধ করে থাকেন তবে আপনি ভিএস 15.7 বা উচ্চতর এবং সি # 7.3 বা তার বেশি ব্যবহার করার কারণে আপনি দেখতে পাবেন যে বাক্য গঠনটি পুরোপুরি ঠিক আছে।


1
আপনি কোন ভিএস সংস্করণটি ব্যবহার করছেন?
mshwf

1
@ মোহামেদশাহাফ আমি বিশ্বাস করি যে এটির সংস্করণ 15.7 রয়েছে যা সি # 7.3 এর জন্য সমর্থন রয়েছে
প্যাট্রিক রবার্টস

1
আমি মনে করি এটি নিজেরাই টাইপ প্যারামিটার হিসাবে where T : struct, Enumপাস করা এড়াতে লিখতে ভাল System.Enum
মারিউজ পাভেলস্কি

@ মারিউসপওয়েলস্কি পছন্দ করি আমি লিখি struct, Enum। আমার যুক্তি এখানে উত্তর এবং মন্তব্যে ব্যাখ্যা করা হয় ।
স্টিফেন কেনেডি

রিশার্পার তথ্য সত্যিই আমাকে সাহায্য করেছিল। নোটের সর্বশেষ পূর্বরূপ সংস্করণটি এই বৈশিষ্ট্যটিকে সমর্থন করে।
ডালসফ্ট

11

আমি dimarzionist দ্বারা নমুনা পরিবর্তন। এই সংস্করণটি কেবল এনামগুলির সাথে কাজ করবে এবং স্ট্রাইকগুলি প্রবেশ করতে দেবে না।

public static T ParseEnum<T>(string enumString)
    where T : struct // enum 
    {
    if (String.IsNullOrEmpty(enumString) || !typeof(T).IsEnum)
       throw new Exception("Type given must be an Enum");
    try
    {

       return (T)Enum.Parse(typeof(T), enumString, true);
    }
    catch (Exception ex)
    {
       return default(T);
    }
}

13
ব্যর্থতায় আমি ডিফল্ট মানটি ফেরত দেব না; আমি ব্যতিক্রমটি প্রচার করতে দিতাম (যেমন এটি এনাম.পার্সের সাথে হয়)। পরিবর্তে, একটি পুল ফিরিয়ে ট্রাইপার্স ব্যবহার করুন এবং আউট প্যারাম ব্যবহার করে ফলাফলটি ফিরিয়ে দিন।
সিম্পসন

1
ওপি চায় এটি কেস-সংবেদনশীল হোক, এটি নয়।
কনরাড মোরাওস্কি

9

আমি কোডটি কিছুটা উন্নত করার চেষ্টা করেছি:

public T LoadEnum<T>(string value, T defaultValue = default(T)) where T : struct, IComparable, IFormattable, IConvertible
{
    if (Enum.IsDefined(typeof(T), value))
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }
    return defaultValue;
}

1
এটি গ্রহণযোগ্য উত্তরের চেয়ে ভাল কারণ এটি আপনাকে কল করার অনুমতি দেয় defaultValue.ToString("D", System.Globalization.NumberFormatInfo.CurrentInfo)যদিও এটি আপনি জানেন না যে এটি কোন ধরণের এনাম, কেবলমাত্র এটি বস্তুটি একটি এনাম।
স্টায়ফেল

1
যদিও অগ্রিম চেক IsDefinedক্ষেত্রে সংবেদনশীলতা নষ্ট করবে। বিপরীতে Parse, IsDefinedকোন ignoreCaseযুক্তি নেই, এবং এমএসডিএন বলছে এটি কেবল সঠিক কেসের সাথে মেলে
নাইয়ারগডস

5

আমার এনাম মানের সাথে যুক্ত পাঠ্যের সাথে এনাম ব্যবহার করার প্রয়োজন রয়েছে সেখানে আমার নির্দিষ্ট প্রয়োজনীয়তা রয়েছে। উদাহরণস্বরূপ আমি যখন ত্রুটি নির্দিষ্ট করতে এনাম ব্যবহার করি তখন ত্রুটির বিবরণ বর্ণনা করার জন্য এটি টাইপ করে।

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());
}

4

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

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;
      }
}

1
আপনি কেস insensitivity প্রয়োজন হয়, তাহলে কেবল প্রতিস্থাপন return (TValue)Enum.Parse(typeof (TValue), value);দ্বারাreturn (TValue)Enum.Parse(typeof (TValue), value, true);
পাওলো সান্তোসের

3

আকর্ষণীয়ভাবে যথেষ্ট, স্পষ্টতই অন্যান্য ল্যাজেগুলিতে এটি সম্ভব (পরিচালনা করা সি ++, সরাসরি আইএল)।

উদ্ধৃতি থেকে:

... উভয় সীমাবদ্ধতাগুলিই আসলে বৈধ আইএল উত্পাদন করে এবং অন্য ভাষায় লিখিত হলে সি # দ্বারা সেবন করতেও পারে (আপনি এই সীমাবদ্ধতাগুলিকে ম্যানেজড সি ++ বা আইএল তে ঘোষণা করতে পারেন)।

কে জানে


2
সি ++ এর জন্য পরিচালিত এক্সটেনশনের জেনেরিকদের জন্য কোনও সমর্থন নেই, আমার ধারণা আপনার অর্থ সি ++ / সিএলআই।
বেন ভয়েগট

3

এটি আমার গ্রহণ। উত্তর এবং এমএসডিএন থেকে মিলিত

public static TEnum ParseToEnum<TEnum>(this string text) where TEnum : struct, IConvertible, IComparable, IFormattable
{
    if (string.IsNullOrEmpty(text) || !typeof(TEnum).IsEnum)
        throw new ArgumentException("TEnum must be an Enum type");

    try
    {
        var enumValue = (TEnum)Enum.Parse(typeof(TEnum), text.Trim(), true);
        return enumValue;
    }
    catch (Exception)
    {
        throw new ArgumentException(string.Format("{0} is not a member of the {1} enumeration.", text, typeof(TEnum).Name));
    }
}

এমএসডিএন উত্স


2
এটি সত্যিকার অর্থে বোঝায় না। যদি TEnumপ্রকৃতপক্ষে এনুম টাইপ হয় তবে textএকটি খালি স্ট্রিং হয় তবে আপনি ArgumentException"টেনাম অবশ্যই এনুম টাইপ হওয়া উচিত" হলেও একটি প্রবাদ পাবেন ।
নিক

3

বিদ্যমান উত্তরগুলি সি # <= 7.2 হিসাবে সত্য। তবে, নিম্নলিখিতগুলিকে অনুমতি দেওয়ার জন্য একটি সি # ভাষার বৈশিষ্ট্য অনুরোধ (একটি কোরফেক্স বৈশিষ্ট্য অনুরোধের সাথে আবদ্ধ ) রয়েছে;

public class MyGeneric<TEnum> where TEnum : System.Enum
{ }

লেখার সময়, বৈশিষ্ট্যটি ভাষা বিকাশ সভায় "আলোচনায়"।

সম্পাদনা

অনুযায়ী nawfal এর তথ্য, এই সি # চালু হচ্ছে 7.3


1
সেখানে আকর্ষণীয় আলোচনা, ধন্যবাদ। এখনও প্রস্তর হিসাবে কিছুই সেট করা হয়নি (এখনও হিসাবে)
johnc

1
@johnc, খুব সত্য কিন্তু মূল্য একটি নোট এবং এটি হল একটি প্রায়শই জিজ্ঞাসা বৈশিষ্ট্য। এতে আসার
পক্ষে সুস্পষ্ট

1

1

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

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>();
}

1

আমি ক্রিস্টোফার কারেনসের সমাধান আইএল ব্যবহার করে পছন্দ করেছিলাম তবে যারা তাদের বিল্ডিং প্রক্রিয়াতে এমএসআইএল অন্তর্ভুক্ত করার কৌশলপূর্ণ ব্যবসায়ের সাথে মোকাবিলা করতে চান না তাদের জন্য আমি সি # তে অনুরূপ ফাংশন লিখেছিলাম।

দয়া করে নোট করুন যে আপনি জেনেরিক সীমাবদ্ধতাটি ব্যবহার করতে পারবেন না where T : 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;
}

1

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

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);
        }
    }
}

1

আমি একটি এক্সটেনশন পদ্ধতি তৈরি করেছি 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

এটি সম্ভবত কার্যকর হলেও, এটির প্রশ্নের প্রায় কোনও প্রাসঙ্গিকতা নেই।
কোয়েটজলকোটল

1

যেমন আগে অন্য উত্তরে বলা হয়েছে; যদিও এটি উত্স-কোডে প্রকাশ করা যায় না এটি আসলে আইএল স্তরে করা যেতে পারে। @Christopher Currens উত্তর দেখায় যে আইএল এটি কী করে।

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

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

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

এবং ফডি সীমাবদ্ধতা উপস্থিত হওয়ার জন্য প্রয়োজনীয় আইএল যুক্ত করবে। প্রতিনিধিদের বাধা দেওয়ার অতিরিক্ত বৈশিষ্ট্যটিও নোট করুন:

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

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

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


1

এটি আমার বাস্তবায়ন। মূলত, আপনি কোনও বৈশিষ্ট্য সেটআপ করতে পারেন এবং এটি কাজ করে।

public static class EnumExtensions
    {
        public static string GetDescription(this Enum @enum)
        {
            Type type = @enum.GetType();
            FieldInfo fi = type.GetField(@enum.ToString());
            DescriptionAttribute[] attrs =
                fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
            if (attrs.Length > 0)
            {
                return attrs[0].Description;
            }
            return null;
        }
    }

0

যদি পরে সরাসরি কাস্টিং ব্যবহার করা ঠিক থাকে তবে আমার ধারণা আমি 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);

ব্যবহারের Enum.ToObject()ফলে আরও নমনীয় ফল পাওয়া যাবে। এতে যোগ হয়েছে, আপনি কেস সংবেদনশীলতা ছাড়াই স্ট্রিং তুলনা করতে পারবেন যা কল করার প্রয়োজনকে অস্বীকার করবেToLower()
ডিস্কজঙ্কি

-6

কেবল সম্পূর্ণতার জন্য, নিম্নলিখিতটি একটি জাভা সমাধান is আমি নিশ্চিত যে সি # তেও এটি করা যেতে পারে। কোডে কোথাও প্রকারটি নির্দিষ্ট করে দেওয়া এড়ানো যায় - পরিবর্তে, আপনি যে স্ট্রিংকে বিশ্লেষণের চেষ্টা করছেন সেগুলিতে এটি নির্দিষ্ট করে।

সমস্যাটি হ'ল স্ট্রিংটি কোন অঙ্কের সাথে মেলে তা জানার কোনও উপায় নেই - সুতরাং উত্তরটি সেই সমস্যাটি সমাধান করা।

কেবল স্ট্রিংয়ের মান গ্রহণ করার পরিবর্তে, একটি স্ট্রিং গ্রহণ করুন যা "এনুমারেশন.ভ্যালু" আকারে গণনা এবং মান উভয়ই রাখে। ওয়ার্কিং কোডটি নীচে রয়েছে - জাভা 1.8 বা তার পরে প্রয়োজন। এটি এক্সএমএলকে আরও সুনির্দিষ্ট করে তুলবে যেমন আপনি কেবল রঙ = "লাল" এর পরিবর্তে রঙ = "কালার.রেড" এর মতো কিছু দেখতে পাবেন।

আপনি এনাম নেম ডট মান নামযুক্ত একটি স্ট্রিং সহ গ্রহনযোগ্য গণ্যমূল্য () পদ্ধতিতে কল করবেন।

পদ্ধতিটি আনুষ্ঠানিক গণিত মান প্রদান করে।

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;


public class EnumFromString {

    enum NumberEnum {One, Two, Three};
    enum LetterEnum {A, B, C};


    Map<String, Function<String, ? extends Enum>> enumsByName = new HashMap<>();

    public static void main(String[] args) {
        EnumFromString efs = new EnumFromString();

        System.out.print("\nFirst string is NumberEnum.Two - enum is " + efs.acceptEnumeratedValue("NumberEnum.Two").name());
        System.out.print("\nSecond string is LetterEnum.B - enum is " + efs.acceptEnumeratedValue("LetterEnum.B").name());

    }

    public EnumFromString() {
        enumsByName.put("NumberEnum", s -> {return NumberEnum.valueOf(s);});
        enumsByName.put("LetterEnum", s -> {return LetterEnum.valueOf(s);});
    }

    public Enum acceptEnumeratedValue(String enumDotValue) {

        int pos = enumDotValue.indexOf(".");

        String enumName = enumDotValue.substring(0, pos);
        String value = enumDotValue.substring(pos + 1);

        Enum enumeratedValue = enumsByName.get(enumName).apply(value);

        return enumeratedValue;
    }


}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.