ටී එනුම් එකකට සීමා කරන සාමාන්‍ය ක්‍රමයක් සාදන්න


1204

එම Enum.Parseසංකල්පය දීර් extend කිරීම සඳහා මම ශ්‍රිතයක් ගොඩනඟමි

  • එනුම් අගයක් සොයාගත නොහැකි නම් පෙරනිමි අගයක් විග්‍රහ කිරීමට ඉඩ දෙන්න
  • නඩුව සංවේදී නොවේ

එබැවින් මම පහත සඳහන් දේ ලිව්වෙමි.

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ශ්‍රිතය අනුකරණය කර ගුණාංගයක් ලෙස වර්ගයක් සම්මත කිරීමට සිදුවනු ඇත , එමඟින් ඔබේ කේතයට කැත බොක්සිං අවශ්‍යතාවයට බල කරයි.

සංස්කරණය කරන්න පහත ඇති සියලුම යෝජනා බෙහෙවින් අගය කර ඇත, ස්තූතියි.

පදිංචි වී ඇත (සිද්ධි සංවේදීතාව පවත්වා ගැනීම සඳහා මම ලූපය අතහැර දමා ඇත - XML ​​විග්‍රහ කිරීමේදී මම මෙය භාවිතා කරමි)

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) ජූලියන් ලෙබොස්කේන් මෑතකදී එම්එස්අයිඑල් හෝ එෆ් # හි සම්පාදක බලහත්කාරයෙන් ටයිප්-ආරක්ෂිත ජනක විසඳුමක් පහළින් පළ කර ඇති අතර එය බැලීමට වටිනවා. විසඳුම පිටුව තව දුරටත් ඉහළට එන්නේ නම් මම මෙම සංස්කරණය ඉවත් කරමි.


10
සමහර විට ඔබ ToLower () වෙනුවට ToUpperInvariant () භාවිතා කළ යුතුය ...
මැක්ස් ගල්කින්

31
H ෂිමී: ඔබ දිගු කිරීමේ ක්‍රමයට අගය වර්ගයක් යැවූ විගසම, ඔබ එහි පිටපතක් මත වැඩ කරමින් සිටින බැවින් ඔබට එහි තත්වය වෙනස් කළ නොහැක.
ගාරෝ යෙරිසරියන්

4
එය පැරණි නූල් එකක් බව දැන ගන්න, ඒවා දේවල් වෙනස් කර ඇත්දැයි නොදනී, නමුත් දිගු කිරීමේ ක්‍රම අගය වර්ග සඳහා හොඳින් ක්‍රියා කරයි, ඒවා සැමවිටම එතරම් තේරුමක් නැති බව සහතිකයි, නමුත් මම “පොදු ස්ථිතික ටයිම්ස්පන් තත්පර (මෙම int x) used භාවිතා කර ඇත්තෙමි. "වේට්.ෆෝර් (5. තත්පර ()) හි වාක්‍ය ඛණ්ඩය සක්‍රීය කිරීම සඳහා TimeSpan.FromSeconds (x);}" ආපසු එවන්න
ජෙන්ස්

6
මෙය ප්‍රශ්නයේ කොටසක් නොවන බව වටහා ගන්න, නමුත් String.Equals with StringComparison.InvariantCultureIgnoreCase
Firestrand

Answers:


1015

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 සිට ජනක විද්‍යාව ලබා ගත හැකිය. එබැවින් ඒවා 2005 දී ද ලබා ගත හැකිය.
විවේක්

46
හොඳයි, එසේ නම් එය වඩාත් අවහිර කරන්න, ඔබ මෙම මාර්ගයට යාමට තෝරා ගන්නේ නම් ... "පන්තියේ ටෙස්ට් ක්ලාස් <T> භාවිතා කරන්න, එහිදී ටී: struct, IComparable, IFormattable, IConvertible"
රිකාඩෝ

106
තවත් යෝජනාවක් වන්නේ TEnum හඳුනාගැනුම සමඟ සාමාන්‍ය වර්ගය නිර්වචනය කිරීමයි. මේ අනුව: පොදු TEnum GetEnumFromString <TEnum> (නූල් අගය) එහිදී TEnum: struct, IConvertible, IComparible, IFormattable {}
Lisa

12
අනෙක් අතුරුමුහුණත් ඇතුළත් කිරීමෙන් ඔබට බොහෝ දේ ලැබෙන්නේ නැත. සාමාන්‍ය විස්තාරණ ක්‍රමයක ඇති බාධක සඳහා මෙය විශේෂයෙන් සත්‍ය වේ, එය එන්මූම් මත ක්‍රියාත්මක කිරීම සඳහා අතිශයින්ම පහසුය, එම ව්‍යාප්ති ක්‍රම ඔබේ සියලු වස්තූන් ආසාදනය කරන වෛරසයක් වැනි ය. IConvertable අවම වශයෙන් එය තරමක් අඩු කරයි.
රුස්බිෂොප්

3
C # 7.3
Yahoo Serious

679

මෙම අංගය අවසානයේ C # 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;
}

ඔබේ C # ව්‍යාපෘතියේ භාෂා අනුවාදය 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

පහත දැක්වෙන C # කේතය සමඟ:

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
}

අවාසනාවට, මෙයින් අදහස් කරන්නේ ඔබේ කේතයේ මෙම කොටස C # වෙනුවට MSIL හි ලියා තිබීමයි, එකම අමතර වාසිය වන්නේ ඔබට මෙම ක්‍රමය සීමා කිරීමට හැකි වීමයි System.Enum. එය වෙනම එකලස් කිරීමකට සම්පාදනය වන නිසා එය ද යම් ආකාරයක බමුණෙකි. කෙසේ වෙතත්, එයින් අදහස් කරන්නේ ඔබ එය ඒ ආකාරයෙන් යෙදවිය යුතු බවයි.

රේඛාව ඉවත් .assembly MyThing{}කර පහත පරිදි ilasm ආයාචනය කිරීමෙන්:

ilasm.exe /DLL /OUTPUT=MyThing.netmodule

එකලස් කිරීමක් වෙනුවට ඔබට නෙට් මොඩියුලයක් ලැබේ.

අවාසනාවකට මෙන්, VS2010 (සහ ඊට පෙර, පැහැදිලිවම) නෙට් මොඩියුල යොමුව එක් කිරීමට සහාය නොදක්වයි, එයින් අදහස් වන්නේ ඔබ නිදොස්කරණය කිරීමේදී එය එකලස් 2 ක් තුළ තැබිය යුතු බවයි. ඔබේ එකලස් කිරීමේ කොටසක් ලෙස ඔබට ඒවා එකතු කළ හැකි එකම ක්‍රමය වන්නේ /addmodule:{files}විධාන රේඛා තර්කය භාවිතා කර ඔබම csc.exe ධාවනය කිරීමයි . MSBuild පිටපතක එය එතරම් වේදනාකාරී නොවනු ඇත . ඇත්ත වශයෙන්ම, ඔබ නිර්භීත හෝ මෝඩ නම්, ඔබට සෑම විටම csc ඔබම අතින් ධාවනය කළ හැකිය. එකලස් කිරීම සඳහා එයට ප්‍රවේශය අවශ්‍ය බැවින් එය නිසැකවම වඩාත් සංකීර්ණ වේ.

ඉතින්, එය .Net හි කළ හැකිය. අමතර වෑයමක් දැරීම වටී ද? ම්ම්, හොඳයි, මම හිතන්නේ මම ඔබට එය තීරණය කිරීමට ඉඩ දෙන්නම්.


විකල්පයක් ලෙස F # විසඳුම

අමතර ණය: 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

පූර්ණ දෘශ්‍ය ස්ටුඩියෝ IDE සහය ඇති ප්‍රසිද්ධ භාෂාවක් බැවින් මෙය නඩත්තු කිරීම පහසුය, නමුත් ඒ සඳහා ඔබේ විසඳුමේ වෙනම ව්‍යාපෘතියක් අවශ්‍යය. කෙසේ වෙතත්, එය ස්වභාවිකව සැලකිය යුතු වෙනස් IL නිෂ්පාදනය (කේතය වන්නේ ඉතා වෙනස්) සහ එය මත යැපෙන FSharp.Coreපමණක් වෙනත් ඕනෑම බාහිර පුස්තකාල වැනි, ඔබේ බෙදා හැරීමේ කොටසක් බවට පත් කිරීමට අවශ්ය වන, පුස්තකාලයක්,.

මෙන්න ඔබට එය භාවිතා කළ හැකි ආකාරය (මූලික වශයෙන් MSIL විසඳුමට සමාන වේ), සහ වෙනත් ආකාරයකින් සමාන ව්‍යුහයන් මත එය නිවැරදිව අසමත් වන බව පෙන්වීමට:

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

68
ඔව්, ඉතා තදබලයි. මම IL හි කේතය කළ හැකි කෙනෙකු සඳහා උපරිම ගෞරවයක්, හා විශේෂාංග ඉහළ භාෂාව මට්ටමින් සහයෝගය ආකාරය දන්නවා - අපි බොහෝ දෙනෙක් තවමත් අයදුම්පත්, ව්යාපාර නීති යටතේ අඩු මට්ටමේ ලෙස දකින වන මට්ටම, UI ගේ, අංගයක් පුස්තකාල, ආදිය .
ටෝනි ජී

13
මා දැන ගැනීමට කැමති දෙය නම් සී # කණ්ඩායම මේ සඳහා තවමත් ඉඩ නොදෙන්නේ මන්ද යන්නයි.
MgSam

25
@MgSam - එරික් ලිපර්ට් වෙතින් :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: මම හේතුව constrains වන පන්තියේ සිට බව සිතන්නේ Tකිරීමට System.Enumසමග සියලු දේ කළ හැකි වන්නේ නැහැ Tකියා ජනතාව බලාපොරොත්තු විය හැකි, C # කතුවරුන් ඔවුන් මෙන්ම සම්පූර්ණයෙන්ම එය තහනම් විය හැක හදුනාගත්තා. මෙම තීරණය අවාසනාවන්ත ලෙස මම සලකමි, එය සී # විසින් කිසියම් විශේෂ System.Enumඅවහිරතා හැසිරවීමක් නොසලකා හැර ඇති හෙයින්, එහි තර්කවලට HasAnyFlags<T>(this T it, T other)වඩා වේගයෙන් Enum.HasFlag(Enum)හා විශාල වශයෙන් ඇණවුම් කරන දීර් extension ක්‍රමයක් ලිවීමට හැකි වනු ඇත .
සුපර්කැට්

9
මම හිතන්නේ නැහැ මම මෙතනින් මෙහාට නොගිය ව්‍යාපෘතියක් තියෙනවා කියලා. සී # 6 යනු 110% සින්ටැක්ටික් සීනි වන අතර මෙය ඇතුල් නොවීය. කපටි කපන්න.
මයිකල් බ්ලැක්බර්න්

220

සී # ≥ 7.3

C # 7.3 සිට (Visual Studio 2017 ≥ v15.7 සමඟ ලබා ගත හැකිය), මෙම කේතය දැන් සම්පූර්ණයෙන්ම වලංගු වේ:

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

සී # ≤ 7.2

අවහිරතා උරුමය අනිසි ලෙස භාවිතා කිරීමෙන් ඔබට නියම සම්පාදකයෙකු බලාත්මක කළ හැක. පහත කේතය එකවර a 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");

සටහන: මෙය C # 5.0 භාෂා පිරිවිතරයේ විශේෂයෙන් සඳහන් කර ඇත:

S වර්ගයේ පරාමිතිය T වර්ගයේ පරාමිතිය මත රඳා පවතී නම්: [...] S අගය සඳහා අවහිරතා තිබීම සහ T යොමු වර්ගය අවහිරතා තිබීම වලංගු වේ. System ලදායී ලෙස මෙය System.Object, System.ValueType, System.Enum සහ ඕනෑම අතුරු මුහුණත් වර්ගයකට T සීමා කරයි.


7
I ඩේවිඩ් අයි.එම්.සී.ඉන්ටොෂ් EnumClassUtils<System.Enum>ඕනෑම System.Enumහා ඕනෑම ව්‍යුත්පන්න වර්ගයකට ටී සීමා කිරීමට ප්‍රමාණවත් වේ . structමත Parseඑවකට සැබෑ නිඛිල වර්ගය තවදුරටත් එය සීමා වේ. ඔබ Enumයම් අවස්ථාවක සීමා කළ යුතුය. එසේ කිරීමට ඔබේ පන්තිය කැදැල්ල කළ යුතුය. Gist.github.com/MrJul/7da12f5f2d6c69f03d79
ජූලියන් ලෙබොස්කේන්

7
පැහැදිලිව කිවහොත්, මගේ ප්‍රකාශය “ප්‍රසන්න නොවේ” ඔබේ විසඳුම පිළිබඳ අදහස් දැක්වීමක් නොවේ - එය සැබවින්ම සුන්දර කඩුල්ලකි. එම්එස් අපට එවැනි කැටි ගැසුණු හැක් භාවිතා කිරීමට බල කරන "ප්‍රසන්න නොවේ".
ඩේවිඩ් අයි. මැකින්ටොෂ්

2
ව්‍යාප්ති ක්‍රම සඳහා ද භාවිතා කළ හැකි වන පරිදි මෙය ක්‍රියාත්මක කිරීමට ක්‍රමයක් තිබේද?
මෝර්ඩ් සුබර්

3
where TClass : classමෙහි ඇති බාධාව කුමක්ද?
tsemer

2
R ට්‍රින්ක්යෝenum DefinitelyNotAnInt : byte { Realize, That, I, Am, Not, An, Int } enum AlsoNotAnInt : long { Well, Bummer }
එම්.ස්ට්‍රාම්

30

සංස්කරණය කරන්න

මෙම ප්‍රශ්නයට දැන් ජූලියන් ලෙබොස්කේන් විසින් විශිෂ්ට ලෙස පිළිතුරු ලබා දී ඇත. මම ද ඔහුගේ පිළිතුර දීර්ඝ කිරීමට කැමති 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(VS2010 / .Net 4 හි හඳුන්වා දී ඇත)
  • විකල්පයක් ලෙස සාමාන්‍ය defaultඅගය භාවිතා කරන්න (VS2005 / .Net 2 හි හඳුන්වා දී ඇත)
  • භාවිතා විකල්ප තර්ක සඳහා පෙරනිමි අගයන් සමඟ (VS2010 / .Net 4 මස හඳුන්වා දුන්) defaultValueසහ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;
    }
}

19

පංතිය සඳහා ස්ථිතික ඉදිකිරීම්කරුවෙකු ඔබට අර්ථ දැක්විය හැකි අතර එය T වර්ගය එනූම් එකක් දැයි පරීක්ෂා කර එය එසේ නොවේ නම් ව්‍යතිරේකයක් විසි කරයි. ජෙෆ්රි රිච්ටර් විසින් සීඑල්ආර් හරහා සීඑල්ආර් නම් පොතේ සඳහන් කළ ක්‍රමය මෙයයි.

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

විග්‍රහ කිරීමේ ක්‍රමයේදී, ඔබට එනුම්.පාර්ස් (ටයිප් (ටී), ආදානය, සත්‍ය) භාවිතා කර නූල් සිට එනුම් දක්වා පරිවර්තනය කළ හැකිය. අවසාන සත්‍ය පරාමිතිය වන්නේ ආදානයේ සිද්ධිය නොසලකා හැරීමයි.


2
සාමාන්‍ය පන්ති සඳහා මෙය හොඳ විකල්පයකි - නමුත් ඇත්ත වශයෙන්ම එය සාමාන්‍ය ක්‍රම සඳහා උපකාරී නොවේ.
මැක්ගර්නගල්

1
එසේම, මෙය සම්පාදනය කරන වේලාවේදී බලාත්මක නොකෙරේ, ඔබ දැනගන්නේ ඔබ විසින් Enum Tඉදිකිරීම්කරු ක්‍රියාත්මක කළ විට පමණක් නොවන බව පමණි . මෙය නිදර්ශන ඉදිකිරීම්කරුවෙකු එනතෙක් බලා සිටීමට වඩා හොඳ වුවත්.
jrh

15

අතිරේක පරීක්‍ෂා කිරීම් සහ දේවල් කිරීමකින් තොරව එනුම් බාධක භාවිතා කරමින් සී # 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 - අවශ්‍ය දෘශ්‍ය ස්ටුඩියෝ අනුවාදය සහ රීෂාපර් සලකා බැලීම

විෂුවල් ස්ටුඩියෝ සඳහා නව වාක්‍ය ඛණ්ඩය හඳුනා ගැනීමට ඔබට අවම වශයෙන් 15.7 අනුවාදය අවශ්‍ය වේ. මයික්‍රොසොෆ්ට් නිකුතු සටහන් වලද සඳහන් කර ඇති බව ඔබට සොයාගත හැකිය, විෂුවල් ස්ටුඩියෝ 2017 15.7 නිකුතු සටහන් බලන්න . මෙම වලංගු ප්‍රශ්නය පෙන්වා දීම ගැන ස්තූතියි o මොහමඩ් එල්ෂවාෆ්.

මගේ නඩුවේ ReSharper 2018.1 මෙම ලිවීමේදී C # 7.3 සඳහා තවමත් සහාය නොදක්වන බව Pls සටහන් කරයි. ReSharper සක්‍රිය කිරීමෙන් එය 'System.Array', 'System.Delegate', 'System.Enum', 'System.ValueType', 'object' යන වර්ග පරාමිති අවහිරතා ලෙස භාවිතා කළ නොහැකි බව පවසන දෝෂයක් ලෙස එනුම් බාධකය ඉස්මතු කරයි . ReSharper යෝජනා කරන්නේ T වර්ගයේ පරාමිති ක්‍රමයේ 'Enum' අවහිරතා ඉවත් කිරීමට ඉක්මන් විසඳුමක් ලෙස ය

කෙසේ වෙතත්, ඔබ මෙවලම් -> විකල්ප -> රීෂාර්පර් අල්ටිමේට් -> ජෙනරල් යටතේ තාවකාලිකව අක්‍රිය කළහොත්, ඔබ VS 15.7 හෝ ඊට වැඩි සහ C # 7.3 හෝ ඊට වැඩි භාවිතා කරන විට සින්ටැක්ස් පරිපූර්ණ බව ඔබට පෙනෙනු ඇත.


1
ඔබ භාවිතා කරන්නේ කුමන VS අනුවාදයද?
mshwf

1
OMohamedElshawaf එය C # 7.3 සඳහා සහය දක්වන 15.7 අනුවාදය බව මම විශ්වාස කරමි
පැට්‍රික් රොබට්ස්

1
ටයිප් පරාමිතිය ලෙස where T : struct, Enumසම්මත වීම වළක්වා ගැනීම සඳහා ලිවීම වඩා හොඳ යැයි මම සිතමි System.Enum.
මාරියස් පවෙල්ස්කි

ArMariuszPawelski වගේ මම ලියනවා struct, Enum. මගේ තර්කය මෙහි පිළිතුර සහ අදහස් දැක්වීමේදී පැහැදිලි කර ඇත .
ස්ටීවන් කෙනඩි

ReSharper තොරතුරු මට ඇත්තටම උදව් කළා. සටහන නවතම පෙරදසුන අනුවාදය මෙම අංගයට සහය දක්වයි.
ඩෝල්සොෆ්ට්

11

මම නියැදිය ඩිමර්සියානිස්ට් විසින් වෙනස් කළෙමි. මෙම අනුවාදය ක්‍රියාත්මක වන්නේ එනුම්ස් සමඟ පමණක් වන අතර ව්‍යුහයන් හරහා යාමට ඉඩ නොදේ.

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
මම අසමත් වූ විට පෙරනිමි අගය ලබා නොදෙමි. මම ව්‍යතිරේකය ප්‍රචාරය කිරීමට ඉඩ දෙමි (එය එනුම් පාර්ස් සමඟ මෙන්). ඒ වෙනුවට, ට්‍රයිපාර්ස් නැවත බූල් එකක් භාවිතා කර ප්‍රති para ලය පිටත පරාමිතියක් භාවිතා කරන්න.
මාර්ක් සිම්සන්

1
OP ට අවශ්‍ය වන්නේ එය සිද්ධි සංවේදී නොවීමයි, මෙය එසේ නොවේ.
කොන්රාඩ් මොරව්ස්කි

10

මම කේතය ටිකක් වැඩි දියුණු කිරීමට උත්සාහ කළෙමි:

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තර්කයක් නොමැති අතර MSDN පවසන්නේ එය හරියටම ගැලපෙන බවයි .
නයර්ගුඩ්ස්

6

C # <= 7.2 අනුව පවතින පිළිතුරු සත්‍ය වේ. කෙසේ වෙතත්, පහත සඳහන් දේ සඳහා ඉඩ දීම සඳහා C # භාෂා විශේෂාංග ඉල්ලීමක් ( corefx විශේෂාංග ඉල්ලීමකට බැඳී ඇත );

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

ලිවීමේදී, විශේෂාංගය භාෂා සංවර්ධන රැස්වීම්වල "සාකච්ඡාවේ" ය.

සංස්කරණය කරන්න

අනුව nawfal ගේ තොරතුරු, මෙම C # හඳුන්වා කොට ඇත 7.3 .

සංස්කරණය 2

මෙය දැන් C # 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;
}

1
එහි රසවත් සාකච්ඡාවක්, ස්තූතියි. තවමත් කිසිවක් ගල් ගසා නැත (තවමත්)
johnc

1
@johnc ඉතා සත්යය නමුත් සටහනක් වටිනාකම හා එය වේ එය නිතරම අසන ලක්ෂණය. ඒ පිළිබඳ සාධාරණ
පරස්පරතා පැමිණේ


1
කරුණාකර මෙම පිළිතුර ඉහළට ඔසවන්න, එය මෙහි ලැයිස්තුවේ වඩා බෙහෙවින් වැඩි විය යුතුය, දැන් විශේෂාංගය පවතී! :)
Pac0

5

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

5

මෙය ප්‍රයෝජනවත් වේ යැයි සිතමු:

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
ඔබ නඩුව අසංවේදී අවශ්ය නම්, හුදෙක් වෙනුවට return (TValue)Enum.Parse(typeof (TValue), value);විසින්return (TValue)Enum.Parse(typeof (TValue), value, true);
පවුලෝ Santos

3

සිත්ගන්නා කරුණ නම්, පෙනෙන හැටියට මෙය වෙනත් භාෂා වල (කළමණාකරන සී ++, අයිඑල් කෙලින්ම) කළ හැකිය.

උපුටා දැක්වීමට:

... අවහිරතා දෙකම ඇත්ත වශයෙන්ම වලංගු IL නිපදවන අතර වෙනත් භාෂාවකින් ලියා ඇත්නම් C # විසින් පරිභෝජනය කළ හැකිය (ඔබට එම සීමාවන් කළමනාකරණ C ++ හෝ IL වලින් ප්‍රකාශ කළ හැකිය).

කව්ද දන්නේ


2
C ++ සඳහා කළමණාකරන දිගු වලට ජනක විද්‍යාව සඳහා කිසිදු සහයක් නොමැත, මම හිතන්නේ ඔබ අදහස් කළේ C ++ / CLI.
බෙන් වොයිග්ට්

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

MSDN ප්‍රභවය


2
මෙය සැබවින්ම තේරුමක් නැත. නම් TEnumඇත්තටම කලින් නිඛිල වර්ගය නමුත් textඇත හිස් අගයක් නම් ඔබ ලබා ArgumentException"TEnum ක නිඛිල වර්ගය විය යුතුය" එය වුවත් මෙසේ.
නික්

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

මම ඔබට නැවත භාවිතා කළ හැකි උපයෝගිතා පන්තියකට විවේක්ගේ විසඳුම ඇතුළත් කර ඇත්තෙමි. ඔබේ වර්ගයේ "කොහේද T: 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);
        }
    }
}

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

එය බොහෝ විට ක්‍රියාත්මක වන අතර, එය ප්‍රශ්නයට කිසිදු අදාලත්වයක් නැත.
quetzalcoatl

1

කලින් වෙනත් පිළිතුරු වල සඳහන් පරිදි; මෙය ප්‍රභව කේතයෙන් ප්‍රකාශ කළ නොහැකි අතර එය ඇත්ත වශයෙන්ම IL මට්ටමින් කළ හැකිය. H ක්‍රිස්ටෝපර් කරන්ස්ගේ පිළිතුරෙන් දැක්වෙන්නේ අයිඑල් ඒ සඳහා ක්‍රියා කරන ආකාරයයි.

සමග Fody ගේ එකතු කරන්න-දී 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> ()
{...}

එනූම්ස් සම්බන්ධයෙන්, ඔබට ඉතා රසවත් එනූම්ස්.නෙට් ද සැලකිල්ලට ගත යුතුය .


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()
DiskJunky

-6

සම්පූර්ණත්වය සඳහා, පහත දැක්වෙන්නේ ජාවා විසඳුමකි. C # හි ද එය කළ හැකි බව මට විශ්වාසයි. කේතයේ ඕනෑම තැනක වර්ගය නියම කිරීමෙන් එය වළක්වයි - ඒ වෙනුවට, ඔබ එය විග්‍රහ කිරීමට උත්සාහ කරන නූල්වල සඳහන් කරයි.

ගැටළුව වන්නේ නූලට ගැලපෙන ගණනය කිරීම් මොනවාදැයි දැන ගැනීමට ක්‍රමයක් නොමැති වීමයි - එබැවින් පිළිතුර එම ගැටළුව විසඳීමයි.

නූල් අගය පමණක් පිළිගැනීම වෙනුවට, ගණන් බැලීම සහ අගය යන දෙකම ඇති නූලක් "enumeration.value" ස්වරූපයෙන් පිළිගන්න. වැඩ කිරීමේ කේතය පහතින් - ජාවා 1.8 හෝ ඊට පසුව අවශ්‍ය වේ. මෙය XML වඩාත් නිරවද්‍ය වනු ඇති අතර ඔබ දකින ආකාරයට වර්ණය = "රතු" වෙනුවට color = "Color.red" වැනි දෙයක් පෙනෙනු ඇත.

ඔබ පිළිගැනීමේ සංඛ්‍යාත්මක අගය () ක්‍රමය අමතන්නේ එනුම් නම තිත අගය නම අඩංගු නූලක් සමඟිනි.

මෙම ක්‍රමය මඟින් විධිමත් ගණනය කළ අගය ලබා දෙයි.

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


}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.