এই বৈশিষ্ট্যটি শেষ পর্যন্ত সি # 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);