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