C# generics, перекрестные ссылки на классы для шаблона состояния

Я пытаюсь попасть в C# generics и создал государственную машину с шаблоном состояния, и теперь я пытаюсь рефакторинг.

у меня есть состояние, которое имеет ссылку на объект, над которым он работает.

public abstract class AbstractState<T> where T : StatefulObject {

    protected T statefulObject;

    public AbstractState(T statefulObject) {
        this.statefulObject = statefulObject;
    }

}

и у меня есть объект, который имеет состояния, это должно иметь ссылку на его текущее состояние.

public abstract class StatefulObject<T> : MonoBehaviour where T : AbstractState<StatefulObject<T>> {

    public T state;

}

но он не работает ("тип не может использоваться в качестве параметра типа" t "в общем типе или методе").

что я хочу достичь чего-то вроде этого :

public class Monster : StatefulObject<MonsterState> {

}

public abstract class MonsterState : AbstractState<Monster> {

}

это возможно? Если это не так, есть еще? Тнх.

1 ответов


вы можете сообщил интерфейсы и дисперсия для достижения этого:

public interface IState<out TObject, in TState>
    where TObject : IStatefulObject<TObject, TState>
    where TState : IState<TObject, TState>
{
}

public interface IStatefulObject<in TObject, out TState>
    where TObject : IStatefulObject<TObject, TState>
    where TState : IState<TObject, TState>
{
}

public abstract class AbstractState<TObject> : IState<TObject, AbstractState<TObject>>
    where TObject : IStatefulObject<TObject, AbstractState<TObject>>
{
    protected TObject Object { get; private set; }

    public AbstractState(TObject obj)
    {
        Object = obj;
    }
}

public abstract class StatefulObject<TState> : IStatefulObject<StatefulObject<TState>, TState>
    where TState : IState<StatefulObject<TState>, TState>
{
    protected TState State { get; set; }
}

public class Monster : StatefulObject<MonsterState>
{
    public Monster()
    {
        State = new IdleMonsterState(this);
    }
}

public abstract class MonsterState : AbstractState<Monster>
{
    protected MonsterState(Monster monster)
        : base(monster)
    {
    }
}

public class IdleMonsterState : MonsterState
{
    public IdleMonsterState(Monster monster)
        : base(monster)
    {
    }
}

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


вы также можете пойти с более простым (но менее сильно типизированным) подходом:

public abstract class AbstractState
{
}

public abstract class StatefulObject
{
}

public abstract class AbstractState<TObject> : AbstractState
    where TObject : StatefulObject
{
    protected TObject Object { get; private set; }

    public AbstractState(TObject obj)
    {
        Object = obj;
    }
}

public abstract class StatefulObject<TState> : StatefulObject
    where TState : AbstractState
{
    protected TState State { get; set; }
}

public class Monster : StatefulObject<MonsterState>
{
}

public abstract class MonsterState : AbstractState<Monster>
{
    protected MonsterState(Monster monster)
        : base(monster)
    {
    }
}

это не гарантирует, что вы не сможете назначить, скажем,PlayerState до Monster, вы должны проверить это во время выполнения.