سؤال

ما هي الطريقة الأكثر فعالية لإنشاء ثابت (لا يتغير أبدًا في وقت التشغيل) رسم الخرائط stringق ل intس؟

لقد حاولت استخدام أ قاموس ثابت, ، لكن ذلك لم ينجح.

يمكنني تنفيذ أ المجمع غير قابل للتغيير مع دلالات مناسبة، ولكن لا يزال هذا لا يبدو صحيحًا تمامًا.


بالنسبة لأولئك الذين سألوا، أنا تنفيذ IDataErrorInfo في فصل تم إنشاؤه وأبحث عن طريقة لإجراء بحث عن اسم العمود في مجموعة الواصفات الخاصة بي.

لم أكن على علم (خطأ مطبعي عند الاختبار!d'oh!) يقبل هذا المفتاح السلاسل، وهذا ما سأستخدمه.شكرًا!

هل كانت مفيدة؟

المحلول

إن إنشاء قاموس ثابت تم إنشاؤه في وقت الترجمة في C# ليس بالمهمة السهلة حقًا.في الواقع، لا شيء من الإجابات هنا يحقق ذلك حقًا.

هناك حل واحد يلبي متطلباتك، على الرغم من أنه ليس بالضرورة حلاً جيدًا؛تذكر أنه وفقًا لمواصفات C#، يتم تجميع جداول حالة التبديل إلى جداول انتقال التجزئة الثابتة.أي أنها قواميس ثابتة، وليست سلسلة من عبارات if-else.لذا فكر في بيان حالة التبديل مثل هذا:

switch (myString)
{
   case "cat": return 0;
   case "dog": return 1;
   case "elephant": return 3;
}

هذا هو بالضبط ما تريد.ونعم، أعلم أنه قبيح.

نصائح أخرى

هناك عدد قليل من المجموعات الثمينة غير القابلة للتغيير في الإطار الحالي.يمكنني التفكير في خيار واحد خالي من الألم نسبيًا في .NET 3.5:

يستخدم Enumerable.ToLookup() - ال Lookup<,> الفئة غير قابلة للتغيير (ولكنها متعددة القيم على RHS)؛يمكنك القيام بذلك من أ Dictionary<,> بسهولة شديدة:

    Dictionary<string, int> ids = new Dictionary<string, int> {
      {"abc",1}, {"def",2}, {"ghi",3}
    };
    ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
    int i = lookup["def"].Single();
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");

هذا هو أقرب شيء يمكنك الوصول إليه إلى "قاموس CONST":

public static int GetValueByName(string name)
{
    switch (name)
    {
        case "bob": return 1;
        case "billy": return 2;
        default: return -1;
    }
}

سيكون المترجم ذكيًا بما يكفي لإنشاء التعليمات البرمجية نظيفة قدر الإمكان.

إذا كنت تستخدم 4.5+ Framework، فسأستخدم ReadOnlyDictionary (أيضًا مجموعة ReadOnly للقوائم) لإجراء تعيينات/ثوابت للقراءة فقط.يتم تنفيذه بالطريقة التالية.

static class SomeClass
{
    static readonly ReadOnlyDictionary<string,int> SOME_MAPPING 
        = new ReadOnlyDictionary<string,int>(
            new Dictionary<string,int>()
            {
                { "One", 1 },
                { "Two", 2 }
            }
        )
}        

لماذا لا تستخدم مساحات الأسماء أو الفئات لتداخل قيمك؟قد يكون غير كامل، لكنه نظيف للغاية.

public static class ParentClass
{
    // here is the "dictionary" class
    public static class FooDictionary
    {
        public const string Key1 = "somevalue";
        public const string Foobar = "fubar";
    }
}

يمكنك الآن الوصول إلى .ParentClass.FooDictionary.Key1، وما إلى ذلك.

لا يبدو أن هناك أي واجهة قياسية غير قابلة للتغيير للقواميس، لذا فإن إنشاء غلاف يبدو الخيار المعقول الوحيد، للأسف.

يحرر:عثر مارك جرافيل على ILookup الذي فاتني - والذي سيسمح لك على الأقل بتجنب إنشاء غلاف جديد، على الرغم من أنك لا تزال بحاجة إلى تحويل القاموس باستخدام .ToLookup().

إذا كانت هذه حاجة مقيدة بسيناريو معين، فقد تكون أفضل حالًا باستخدام واجهة أكثر توجهاً نحو منطق الأعمال:

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}

ولم لا:

public class MyClass
{
    private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };

    public IEnumerable<KeyValuePair<string,int>> MyCollection
    {
        get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top