ما هو أفضل(عند أداء الأمور) طريقة لتنفيذ آلة الدولة في C# ؟

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

سؤال

لقد جاء مع الخيارات التالية:

باستخدام غوتو البيان:

Start:
    goto Data
Data:
    goto Finish
Finish:
    ;

باستخدام بيان التبديل:

switch(m_state) {
    case State.Start:
        m_state = State.Data;
        break;
    case State.Data:            
        m_state = State.Finish;
        break;
    case State.Finish:
        break;
}

باستخدام الانتقال والتحول معا:

switch(m_state) {
    case State.Start:
        goto case State.Data2;
    case State.Data1:
        goto case State.Finish;
    case State.Data2:
        m_state = State.Data1;
        //call to a function outside the state machine
        //that could possibly change the state
        break;
    case State.Finish:
        break;
}

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

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

المحلول

والميزة مع التبديل على غوتو هو أن لديك الدولة في متغير، وليس فقط في مؤشر التعليمة.

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

ومع طريقة التبديل معزولة آلة الدولة، ويمكنك الذهاب إلى أي مكان تريد التعامل مع الأحداث من الخارج. عند العودة إلى آلة الدولة، فإنه لا يزال فقط حيث غادر يوو قبالة. هل يمكن أن يكون حتى آلة الدولة أكثر من واحد يعمل جنبا إلى جنب، وهو أمر غير ممكن مع الإصدار غوتو.

ولست متأكدا من أين أنت ذاهب مع البديل الثالث، يبدو تماما مثل البديل الأول مع التحول عديمة الفائدة حوله.

نصائح أخرى

أنا أفضل للطرفين الدعوة/وظائف العودية.إلى التكيف مع المثال الخاص بك:

returnvalue Start() {
    return Data();
}

returnvalue Data() {
    return Finish();
}

returnvalue Finish() {
    …
}

نظريا ، يمكن تماما المضمنة بحيث مترجم إخراج ما يعادل goto الحل (ومن ثم بنفس السرعة).واقعيا ، C# compiler /غضب ربما لن تفعل ذلك.ولكن لأن الحل هو إلى حد كبير أكثر قابلية للقراءة (حسنا, IMHO), وأود أن استبدال فقط مع goto الحل بعد حذرا جدا القياسي تثبت ذلك هو في الواقع أقل شأنا من حيث السرعة أو كومة تجاوزات تحدث (ليس في هذا حل بسيط ولكن أكبر التلقائية تشغيل إلى هذه المشكلة).

حتى ذلك الحين, كنت بالتأكيد عصا goto case الحل.لماذا ؟ لأنه بعد ذلك كله فوضوي goto المعكرونة جيدا المغطى داخل كتلة الهيكل (على switch كتلة) و السباغيتي لن فسد باقي كود منع بولونيز.

في الختام:الوظيفية البديل هو واضح ولكن بشكل عام عرضة للمشاكل.على goto الحل هو فوضوي.فقط goto case يقدم في منتصف الطريق نظيفة وفعالة الحل.إذا كان الأداء هو في الواقع قصوى (و إنسان هو عنق الزجاجة), انتقل منظم goto case البديل.

وهناك خيار 4TH.

استخدم مكرر لتنفيذ statemachine. هنا هو قصيرة المقالة تبين لكم كيف

ولديه بعض العيوب بالرغم من ذلك. التلاعب في دولة من خارج مكرر غير ممكن.

وأنا أيضا لست متأكدا إذا كان سريع جدا. ولكن يمكنك أن تفعل دائما اختبار.

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

switch(m_state) {
        case State.Start:
                m_state = State.Data;
                break;
        case State.Data:                        
                m_state = ComputeNextState();
                break;
        case State.Finish:
                break;
} 

بل هو أيضا أكثر قابلية للقراءة ، النفقات العامة من بيان التبديل (مقابل غوتو) فقط جعل الفارق في الأداء في ظروف نادرة.

تحرير:

يمكنك استخدام "غوتو القضية" لجعل صغيرة تحسين الأداء:

switch(m_state) {
        case State.Start:
                m_state = State.Data; // Don't forget this line!
                goto case State.Data;
        case State.Data:                        
                m_state = ComputeNextState();
                break;
        case State.Finish:
                break;
} 

ومع ذلك كنت عرضة لخطر من نسيان لتحديث الدولة متغير.والتي قد تسبب خفية الخلل في وقت لاحق (لأنك افترضت أن "m_state" تم تعيين), لذلك أود أن أقترح تجنب ذلك.

وشخصيا انا افضل ثانية واحدة مع غوتو منذ أول واحد سوف تتطلب خطوة حلقة غير الضرورية (على سبيل المثال) للذهاب إلى الدولة الجديدة

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