c# - 自定义字典 ​​TryGetValue 找不到键

标签 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(object 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 枚举来定义状态转换。问题出在我尝试使用 getNext 函数时,因为 TryGetValue 总是返回 false。 GetHashCode 函数接缝工作得很好,所以我不明白问题出在哪里。 谢谢。

最佳答案

问题出在这里:

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

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

enum 类型为覆盖 Equals 做了正确的事,但是(正如@hvd 正确指出的那样),所以你可以这样做

this.currentState.Equals(other.currentState)

关于c# - 自定义字典 ​​TryGetValue 找不到键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28658619/

相关文章:

java - 如果条目已经存在,Map 会保留哪个键实例?

java - C 和 Java 中枚举的区别

c# - 如何将字符串值从 xlworksheet 解析为时间(hh :mm) value into the newsheet?

python - 交换字典中的项目和顺序

c# - dotnet core IdentityModel 不会自省(introspection) token

c++ - std::cout 防止功能出现段错误?

java - Enum.values() 从何而来?

javascript - TypeScript 中定义的对象字面量键的类型是什么?

c# - 通过 Web 服务将数据从 Sql Server 移动到 Excel

c# - 将变量从 C# - IronPython 传递到 Python 脚本