2015-03-26 6 views
0

Я пытаюсь создать свою собственную машину состояний, но столкнулся с некоторыми проблемами в отношении списков классов с общим типом. Мой код выглядит следующим образом.Как создать список классов с параметром generic type в C#?

State.cs:

using UnityEngine; 
using System.Collections; 

public abstract class State<T> where T:StateMachine 
{ 

    public T sm; 

    public State() 
    { 
    } 

    public virtual void OnEnter() 
    { 
    sm.currentState = sm.futureState; 
    } 

    public abstract void OnExit(); 
    public abstract void OnLoop(); 

} 

StateMachine.cs:

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

public abstract class StateMachine : MonoBehaviour 
{ 
    public List<State<T>> stateList = new List<T>>(); 
    public int currentState = -1; 
    public int futureState; 

    protected virtual void Start() 
    { 
    foreach (State<T> s in stateList) 
    { 
     s.sm = this; 
    } 
    } 

    protected virtual void Update() 
    { 
    if (currentState != futureState) 
    { 
     stateList[futureState].OnEnter(); 
    } 

    stateList[currentState].OnLoop(); 

    if (currentState != futureState) 
    { 
     stateList[currentState].OnExit(); 
    } 

    } 

} 

TestStateMachine.cs:

using UnityEngine; 
using System.Collections; 

public class TestStateMachine : StateMachine 
{ 

    public enum StateNames:int 
    { 
    State1, 
    State2, 
    }; 

    public KeyCode kc; 

    // Use this for initialization 
    protected override void Start() 
    { 
    stateList.Add(new TestStateMachineFirstState()); 
    stateList.Add(new TestStateMachineSecondState()); 
    base.Start(); 
    } 

} 

public class TestStateMachineFirstState : State<StateMachine> 
{ 

    public override void OnEnter() 
    { 
    Debug.Log("SM1 OnEnter"); 
    base.OnEnter(); 
    } 

    public override void OnLoop() 
    { 
    Debug.Log("SM1 OnLoop"); 

    if (Input.GetKeyDown(sm.kc)) 
    { 
     sm.futureState = (int)TestStateMachine.StateNames.State2; 
    } 

    } 

    public override void OnExit() 
    { 
    Debug.Log("SM1 OnExit"); 
    } 

} 

public class TestStateMachineSecondState : State<StateMachine> 
{ 

    public override void OnEnter() 
    { 
    Debug.Log("SM2 OnEnter"); 
    base.OnEnter(); 
    } 

    public override void OnLoop() 
    { 
    Debug.Log("SM2 OnLoop"); 

    if (Input.GetKeyDown(sm.kc)) 
    { 
     sm.futureState = (int)TestStateMachine.StateNames.State1; 
    } 

    } 

    public override void OnExit() 
    { 
    Debug.Log("SM2 OnExit"); 
    } 

} 

Я получаю ошибку CS0246: Type or namespace name T cannot be found (или что-то, что звучит подобное).

Мое состояние машины «функции», если я заменю все State<T> и State<TestStateMachine> с State<StateMachine> и если (Input.GetKeyDown(sm.kc)) с (Input.GetKeyDown(KeyCode.A)).

Но это не идеальный вариант, поскольку я не смог бы получить переменные с компьютеров состояния детей. Есть ли способ сохранить эту структуру (как бы плохо она ни была), или я должен попробовать другой подход к использованию государственных машин?

+2

* Где * вы получаете сообщение об ошибке? Можете ли вы воспроизвести его с меньшим количеством кода? И можете ли вы правильно отложить свой код? Это сделало бы его намного легче читать ... –

+0

Мое лучшее предположение, что у вас есть некоторые проблемы при добавлении экземпляров в список >, но дайте некоторые пояснения. –

+0

Ну, для начала, есть следующее: 'public List > stateList = new List >();' –

ответ

1

Можно заметить, что если вы посмотрите на сообщение об ошибке компилятора, он укажет исходный файл и номер строки, в которой была обнаружена ошибка. Это обычно помогает выявить проблему.

Проблема заключается в следующем:

public abstract class StateMachine : MonoBehaviour 
{ 
    public List<State<T>> stateList = new List<T>>(); 
    ... 

T не имеет никакого значения в этом классе, как это не общий класс или метод. Следовательно, компилятор понятия не имеет, что делать с State<T> или List<T.

Вторая проблема состоит в том, что

public List<State<T>> stateList = new List<T>>(); 

не компилирует, даже если в подходящем родового класса или метода: List<State<T>> не совместим с типом List<T>.

0

Причина, по которой вы получаете эту ошибку компиляции, заключается в том, что вы используете параметр типа T типа State в классе StateMachine. Вы можете использовать в curiously recurring template pattern:

class State<T> where T : StateMachine 
class StateMachine<T> where T : StateMachine 
class RealStateMachine : StateMachine<RealStateMachine> 

Однако, это может быть очень запутанным. Если вы в состоянии, вы должны рассмотреть дизайн, в котором State является неродственным абстрактным классом или интерфейсом.

+0

Ну, ваш метод не совсем сработал, но ваш ответ дал мне представление, которое после экспериментов работало просто отлично. Благодарю. –

Смежные вопросы