أفضل طريقة لتمثيل التعداد ذو المعلمات في C#؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

هل هناك أي حلول جيدة لتمثيل التعداد ذو المعلمات في C# 3.0؟أنا أبحث عن شيء من هذا القبيل أوكامل أو هاكس لديه.لا يمكنني التفكير إلا في التسلسل الهرمي للفئة مع حقل تعداد بسيط لتسهيل التبديل في الوقت الحالي، ربما هناك أفكار أفضل؟

انظر مثال Ocaml أدناه في أحد الردود، يتبع رمز Haxe:

enum Tree {
   Node(left: Tree, right: Tree);
   Leaf(val: Int);
}
هل كانت مفيدة؟

المحلول

نظرًا لعدم معرفتي بـ OCaml أو Haxe، ولم أكن ذكيًا بما يكفي لفهم التفسيرات الأخرى، فقد ذهبت وبحثت عن وثائق التعداد Haxe - يبدو أن الجزء الخاص بـ "Enum Type Parameters" الموجود بالأسفل هو الجزء ذو الصلة.

وفهمي بناء على ذلك هو كما يلي:

التعداد "العادي" هو في الأساس قيمة تقتصر على الأشياء التي حددتها في تعريف التعداد الخاص بك.مثال C#:

enum Color{ Red, Green, Yellow, Blue };
Color c = Color.Red;

c يمكن أن يكون إما Red, Green, Yellow, ، أو Blue, ، ولكن لا شيء آخر.

في Haxe، يمكنك إضافة أنواع معقدة إلى التعدادات، مثال مفتعل من صفحتهم:

enum Cell<T>{ 
  empty; 
  cons( item : T, next : Cell<T> )
}

Cell<int> c = <I don't know>;

ما هذا يبدو يعني ذلك c يقتصر على كونها القيمة الحرفية empty (مثل تعدادات C# القديمة)، أو يمكن أن تكون أيضًا نوعًا معقدًا cons(item, next), ، أين item هو T و next هو Cell<T>.

نظرًا لعدم استخدام هذا من قبل، يبدو أنه من المحتمل أن يقوم بإنشاء بعض الأنواع المجهولة (مثل الطريقة التي يعمل بها برنامج التحويل البرمجي C# عندما تفعل ذلك) new { Name='Joe'}.
عندما تقوم "بالوصول" إلى قيمة التعداد، عليك الإعلان عنها item و next عند القيام بذلك، يبدو أنها مرتبطة بالمتغيرات المحلية المؤقتة.

مثال Haxe - يمكنك رؤية استخدام "التالي" كمتغير محلي مؤقت لسحب البيانات من بنية السلبيات المجهولة:

switch( c ) {
  case empty : 0;
  case cons(item,next): 1 + cell_length(next);
}

لأكون صادقًا، لقد أذهلني هذا عندما "نقرت" على ما يبدو أنه يفعله.يبدو الأمر قويًا بشكل لا يصدق، وأستطيع أن أرى سبب بحثك عن ميزة مماثلة في C#.

تعدادات C# تشبه إلى حد كبير تعدادات C/++ التي تم نسخها منها في الأصل.إنها في الأساس طريقة لطيفة للقول #define Red 1 حتى يتمكن المترجم من إجراء المقارنات والتخزين باستخدام الأعداد الصحيحة بدلاً من السلاسل عند التمرير Color الأشياء حولها.

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

public interface ICell<T> {
   T Item{ get; set; }
   ICell<T>{ get; set; }
}

class Cons<T> : ICell<T> {
  public T Item{ get; set; } /* C#3 auto-backed property */
  public Cell<T> Next{ get; set; }
}

class EmptyCell<T> : ICell<T>{
  public T Item{ get{ return default(T); set{ /* do nothing */ }; }
  public ICell<T> Next{ get{ return null }; set{ /* do nothing */; }
}

ثم يمكن أن يكون لديك List<ICell<T>> والتي من شأنها أن تحتوي على العناصر والخلية التالية، ويمكنك إدراجها EmptyCell في النهاية (أو فقط احصل على Next مرجع تم تعيينه بشكل صريح على null).المزايا ستكون ذلك بسبب EmptyCell لا يحتوي على متغيرات الأعضاء، ولن يتطلب أي مساحة تخزين (مثل empty في هاكس)، في حين أ Cons سوف الخلية.
قد يقوم المترجم أيضًا بتضمين/تحسين الطرق الموجودة EmptyCell نظرًا لأنهم لا يفعلون شيئًا، فقد تكون هناك زيادة في السرعة مقارنة بمجرد وجود ملف Cons مع تعيين بيانات العضو على قيمة خالية.

أنا لا أعرف حقا.أرحب بأي حلول أخرى ممكنة لأنني لست فخورًا بشكل خاص بالحل الخاص بي :-)

نصائح أخرى

إستخدم فصل مع خصائص ثابتة لتمثيل قيم التعداد.يمكنك، اختياريًا، استخدام مُنشئ خاص لإجبار جميع المراجع إلى الفصل على المرور عبر خاصية ثابتة.

نلقي نظرة على System.Drawing.Color فصل.ويستخدم هذا النهج.

C# (إطار عمل .NET بشكل عام، على حد علمي) لا يدعم التعدادات ذات المعلمات مثل Java.ومع ذلك، قد ترغب في إلقاء نظرة على السمات.بعض الميزات التي يستطيع تعداد Java توفيرها قابلة للتنفيذ إلى حد ما من خلال السمات.

ما الخطأ في مجرد استخدام الفصل الدراسي لهذا؟إنه أمر قبيح، ولكن هذه هي الطريقة التي فعل بها مستخدمو Java ذلك حتى حصلوا على دعم Enum المدمج في اللغة!

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