自定义词典TryGetValue找不到键

时间:2015-02-22 13:56:59

标签: c# dictionary enums hashcode

我正在尝试创建一个像状态机一样工作的基类,它可以接受任何类型的枚举:

    public class BaseFSM <T> where T : struct, IConvertible
{

    //Basic class that denote the transition between one state and another
    public class StateTransition
    {
        public  T currentState { get; set; }
        public  T nextState { get; set; }           

        //StateTransition Constructor
        public StateTransition(T currentState, T nextState)
        {
            this.currentState = currentState;
            this.nextState = nextState;
        }

        public override int GetHashCode()
        {
            return 17 + 31 * this.currentState.GetHashCode() + 31 * this.nextState.GetHashCode();;
        }

        public override bool Equals(object obj)
        {
            StateTransition other = obj as StateTransition;
            return other != null && this.currentState as Enum == other.currentState as Enum && this.nextState as Enum == other.nextState as Enum;
        }
    }

    protected Dictionary<StateTransition, T> transitions; //All the transitions inside the FSM
    public T currentState;
    public T previusState;

    protected BaseFSM() {
        // Throw Exception on static initialization if the given type isn't an enum.
        if(!typeof (T).IsEnum) 
            throw new Exception(typeof(T).FullName + " is not an enum type.");
    }

    private T GetNext(T next)
    {
        StateTransition transition = new StateTransition(currentState, next);
        T nextState;
        if (!transitions.TryGetValue(transition, out nextState))
            throw new Exception("Invalid transition: " + currentState + " -> " + next);
        return nextState;


    }
}

如您所见,我定义了GetHashCode()和Equals(对象obj)。这是我的子类的实现:

public class FSMPlayer : BaseFSM<PlayerState>
{   
    public FSMPlayer() : base()
    {           
        this.currentState = PlayerState.Idle;
        this.transitions = new Dictionary<StateTransition, PlayerState>
        {
            { new StateTransition(PlayerState.Idle, PlayerState.Run), PlayerState.Run }, //0
            { new StateTransition(PlayerState.Run, PlayerState.Jump), PlayerState.Jump }, //1
        };  
    }
}

正如您在我的子类中看到的,我正在使用我的PlayerState Enum来定义状态转换。当我尝试使用getNext函数时问题是因为TryGetValue总是返回false。 GetHashCode函数接缝工作得很好,所以我无法理解问题所在。 感谢。

2 个答案:

答案 0 :(得分:3)

问题在于:

this.currentState as Enum == other.currentState as Enum

Enum是一种引用类型,因此您的枚举会被装入一个(新的,唯一的)对象中。因此,它不再与任何其他盒装实例进行比较。

enum类型做正确的事情以覆盖Equals,但是(因为@hvd正确指出),所以你可以做到

this.currentState.Equals(other.currentState)

答案 1 :(得分:0)

您可能还想阅读此问题的答案,以了解为何不建议在枚举上调用getHashCode。

Using GetHashCode for getting Enum int value