متى تستخدم التعداد ، ومتى يتم استبدالها بفصل مع أعضاء ثابتين؟

StackOverflow https://stackoverflow.com/questions/2119714

سؤال

لقد حدث لي مؤخرًا أن التعداد التالي (العينة) ...

enum Color
{
    Red,
    Green,
    Yellow,
    Blue
}

... يمكن استبدالها بفئة أكثر آمنة على ما يبدو:

class Color
{
    private Color() { }

    public static readonly Color   Red      = new Color();
    public static readonly Color   Green    = new Color();
    public static readonly Color   Yellow   = new Color();
    public static readonly Color   Blue     = new Color();
}

مع "النوع الآمن" ، أعني أن البيان التالي سيعمل إذا Color كان التعداد ، ولكن ليس لو Color كانت الفصل أعلاه:

var nonsenseColor = (Color)17;    // works if Color is an enum

سؤالين:

1) هل هناك اسم مقبول على نطاق واسع لهذا النمط (استبدال التعداد بفئة آمنة من النوع)؟

2) في أي حالات يجب أن يستخدم المرء التعدادات ، ومتى سيكون الفصل أكثر ملاءمة؟

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

المحلول

التعدادات رائعة لمعلومات الحالة الخفيفة. على سبيل المثال ، سيكون تعداد اللون الخاص بك (باستثناء الأزرق) جيدًا للاستعلام عن حالة إشارة المرور. اللون الحقيقي جنبًا إلى جنب مع مفهوم اللون الكامل وجميع أمتعته (ألفا ، مساحة اللون ، إلخ) لا يهم ، تمامًا ما هو الضوء. :

[Flags()]
public enum LightColors
{
    unknown = 0,
    red = 1,
    yellow = 2,
    green = 4,
    green_arrow = 8
}

يمكن تعيين حالة الضوء الحالية على النحو التالي:

LightColors c = LightColors.red | LightColors.green_arrow;

والاستعلام عن:

if ((c & LightColors.red) == LightColors.red)
{
    //Don't drive
}
else if ((c & LightColors.green_arrow) == LightColors.green_arrow)
{
    //Turn
}

سيتمكن أعضاء ألوان الطبقة الثابتة من دعم هذه الحالة المتعددة دون وظائف إضافية.

ومع ذلك ، فإن أعضاء الفصل الثابت رائعون للكائنات الشائعة الاستخدام. ال System.Drawing.Color الأعضاء هي أمثلة رائعة لأنها تمثل ألوانًا معروفة تحتوي على مُنشئين غامضة (إلا إذا كنت تعرف ألوانك السداسية). إذا تم تنفيذها كتعبير ، فسيتعين عليك القيام بشيء مثل هذا في كل مرة تريد فيها استخدام القيمة كون:

colors c = colors.red;
switch (c)
{
    case colors.red:
        return System.Drawing.Color.FromArgb(255, 0, 0);
        break;
    case colors.green:
        return System.Drawing.Color.FromArgb(0,255,0);
        break;
}

لذا ، إذا كان لديك تعداد وتجد أن لديك باستمرار تبديل/حالة/إذا/آخر/أيا كان لاستخلاص كائن ، فقد ترغب في استخدام أعضاء فئة ثابتة. إذا كنت تستفسر فقط عن حالة شيء ما ، فسألتزم بالتعداد. وأيضًا ، إذا كان عليك تمرير البيانات في أزياء غير آمنة على الأرجح ، فمن المحتمل أن تنجو أفضل من نسخة متسلسلة من كائنك.

يحرر:STAKX ، أعتقد أنك تعثرت على شيء مهم ، أيضًا استجابةً لنشر @Anton وهذا التعقيد أو الأهم من ذلك ، من هو معقد؟

من وجهة نظر المستهلك ، أفضّل بشكل كبير system.drawing.color أعضاء فئة ثابتة حول الاضطرار إلى كتابة كل ذلك. ومع ذلك ، من وجهة نظر المنتج ، سيكون من المؤلم أن تكتب كل ذلك. لذا ، إذا كان الأشخاص الآخرون سيستخدمون الكود الخاص بك ، فقد تقوم بتوفير الكثير من المتاعب باستخدام أعضاء الفصل الثابت على الرغم من أن الأمر قد يستغرق 10 مرات حتى يكتب/اختبار/تصحيح. ومع ذلك ، إذا كنت فقط قد تجد أنه من الأسهل استخدام التعدادات والتحويل/التحويل حسب الحاجة.

نصائح أخرى

لقد كنت في الواقع أعاني من شيء مثل هذا قليلاً في العمل.

كان يعتمد على مثال تم نشره بواسطة جون ب في مقالة مدونة جون سكيت "التعدادات المحسنة في C#".

ما لم أحصل على العمل بشكل صحيح دون الكثير من القبح هو تمديد التعداد من خلال استخلاص فئة التعداد الأساسي وإضافة حقول ثابتة إضافية من النوع المستمد.

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

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

وكانت هناك مشكلة أخرى هي التسلسل XML الذي نستخدمه كثيرًا. لقد تجولت في ذلك باستخدام فئتين عامين كنماذج بيانات على متغيرات التعداد على كائنات أعمالنا: واحدة تمثل قيمة تعداد واحدة وواحدة تمثل مجموعة من قيم التعداد التي استخدمتها لتقليد سلوك الأعلام. لقد تعاملوا مع تسلسل XML وإلغاء التسلسل للقيم الفعلية التي تم تخزينها في الخصائص التي كانوا يمثلونها. كان هناك كل من الحمولة الزائدة للمشغل كان كل ما كان ضروريًا لإعادة إنشاء سلوك Bitflag بهذه الطريقة.

هذه هي بعض من المصدر الرئيسي الذي واجهته.

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

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

ليس لديك أي من الكود هنا ولن أتمكن من الوصول إليها في عطلة نهاية الأسبوع وإلا كان بإمكاني عرض المكان الذي ذهبت إليه. ليست جميلة جدا على الرغم من ...: س

بعض الأشياء التي وجدتها في هذه الأثناء ، إذا كان أي شخص آخر مهتمًا:

  • switch الكتل لن تعمل مع التعداد كفئة.

  • المستعمل إمبي ذكر تشابه عينة التعداد المذكورة أعلاه كفئة مع جافا التعداد. يبدو أنه في عالم جافا ، هناك نمط معترف به يسمى Typesafe التعداد; ؛ يبدو أن هذا النمط يعود إلى كتاب جوشوا بلوش جافا فعالة.

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

public enum Legacy : ushort
{
  SomeFlag1 = 0x0001,
  SomeFlag2 = 0x0002,
  // etc...
}

ثم يكون التنقل عند P/Invoke أقل قابلية للقراءة بسبب الصب اللازم لترجمة التعداد إلى القيمة المناسبة.

إذا كان متغير فئة const ، فلن تكون هناك حاجة إلى طاقم.

كلا النهجين صالحين. يجب أن تختار لكل حالة.

يمكنني أن أضيف أن عمليات دعم البتات enums كعلامات (حتى أن هناك [أعلام] سمة لدعم هذه الدلالات وإنتاج سلاسل جميلة من التعداد).

هناك إعادة إنشاء مشابهة للغاية تدعى استبدال التعداد بنمط الاستراتيجية. حسنًا ، في حالتك ، لا يكتمل تمامًا ، نظرًا لأن لونك سلبي ولا يتصرف كاستراتيجية. ومع ذلك ، لماذا لا تفكر في الأمر كحالة خاصة؟

Yup ، الإصدار الأصلي من "java stiveal" من تأليف Joshua Bloch ، الذي صدر قبل Java 1.5 ودعم أصلي لـ Enums في Java ، Typesafe Enum نمط. لسوء الحظ ، فإن أحدث إصدار من الكتاب يستهدف Java> 1.5 ، لذلك يستخدم java reuums بدلاً من ذلك.

ثانياً ، لا يمكنك الإلقاء من int إلى التعداد في جافا.

Color nonsenseColor = (Color)17; // compile-error

لا أستطيع التحدث عن لغات أخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top