4

我创建了一个类状态。对于 State 对象的 Queue,我想测试 Queue 是否已经包含相等值的 State 对象。当数组的所有值都相等且顺序相同时,两个 State 对象(每个都包含一个 2D 布尔数组)是相等的。

这是我的相关代码:

public class State {
   Boolean[,] grid = new Boolean[4,4];

   Public State(Boolean[,] passedGrid){ //Constructor
       grid = Array.Copy(passedGrid, grid, 16);
   }

   public bool Equals(State s2){ //Overloaded equals operator
         for (int x = 0; x < 4; x++){
                 for (int y = 0; y < 4; y++){
                      if (grid[x, y] != s2.grid[x, y]){
                            return false;
                        }
                    }
                }
                return true;
            }

}

    public void testContains(Boolean[] testArray) {
        Queue<State> testQueue = new Queue<State>();
        State s1 = new State(testArray);
        State s2 = new State(testArray);
        testQueue.Enqueue(s1);
        Boolean b = testQueue.Contains(s2);
    }

不幸的是,当调用 testContains() 并且我在最后检查 testQueue.Contains(s2) 的值时,它仍然说测试是错误的,即使它们具有相同的数组值并且 Equals 运算符被重载以进行测试。我必须做什么或改变才能让 Queue.Contains 与我的对象一起工作?我在某处读到,建议在 Equals 重载时重载 getHashCode() 。在这种情况下我需要这样做吗?如果是这样,重载的 getHashCode() 应该做什么?

4

6 回答 6

2

要覆盖 Equals,您需要使用objectas 参数类型和关键字override

所以你可以尝试类似的东西

    public override bool Equals(object obj)
    {
        return Equals(obj as State);
    }
    public bool Equals(State s2)
    { //Overloaded equals operator 
        for (int x = 0; x < 4; x++)
        {
            for (int y = 0; y < 4; y++)
            {
                if (grid[x, y] != s2.grid[x, y])
                {
                    return false;
                }
            }
        }
        return true;
    }

您可能还应该包括测试null

查看重载 Equals() 和运算符 == 的指南(C# 编程指南)

于 2012-10-10T05:32:01.457 回答
0

你应该override 等于

public override bool Equals(object s2)
{
    //implementation
}

为了更好地实践,您应该实现一些其他接口,例如:IEquatable IEqualtable<State>和方法GetHashCode。overrideEquals方法和Equalsin 中的方法IEquatable IEqualtable<T>可以共享一个公共的私有Equals方法。

于 2012-10-10T05:30:11.147 回答
0

您缺少覆盖关键字

   public override bool Equals(Object obj) {
       // fill in the body
    }
于 2012-10-10T05:30:39.620 回答
0

您只需要覆盖类上定义的虚拟方法Object

public override Equals(object other)
{
   if(other is State)
        return Equals((State)other); 
   return base.Equals(other);
}

您需要使用此泛型重载,因为此方法由Contains方法使用,仅添加具有相同名称的实例方法是不够的。

于 2012-10-10T05:32:04.793 回答
0

请在下面找到适合您的代码:

    public class State : Object {
   Boolean[,] grid = new Boolean[4,4];

   public State(Boolean[,] passedGrid){ //Constructor
       Array.Copy(passedGrid, grid, 16);
   }

   public override bool Equals(Object s2){ //Overloaded equals operator
         for (int x = 0; x < 4; x++){
                 for (int y = 0; y < 4; y++){
                      if (grid[x, y] != ((State)s2).grid[x, y]){
                            return false;
                        }
                    }
                }
                return true;
            }

}


    class Program
    {
        Boolean[,] testArray = new Boolean[4, 4];

        public static void Main()
        {
            Program p = new Program();
            p.testContains(p.testArray);
        }

        public void testContains(Boolean[,] testArray)
        {
            Queue<State> testQueue = new Queue<State>();
            State s1 = new State(testArray);
            State s2 = new State(testArray);
            testQueue.Enqueue(s1);
            Boolean b = testQueue.Contains(s2);
            //b is true here
        }

    }
}

另外,请查看以下链接以获取覆盖 Equals 方法的指南:

http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

于 2012-10-10T05:33:11.670 回答
0

对于定义自定义相等关系的类类型,应适用以下内容:

  1. 类应该是不可变的,并且不能封装可变状态。当且仅当此类引用仅用于封装此类对象的 *identities* 或其不可变属性时,不可变类持有对可变对象的引用是可以接受的。
  2. 类必须重写 `bool Equals(Object Other)` 以便在 `Other` 是类的等价实例时返回 `true`(实例与其自身等价;对于可变类型,实例是*唯一*的东西这相当于它自己)。
  3. 该类必须覆盖“int GetHashCode()”,这样任何两个等效实例都将返回相同的值,并且最好是两个任意选择的非等效实例不太可能返回相同的值。
  4. 如果类是密封的,除了执行上述操作外,它还可以为自己的类型实现 `IEquatable`。未密封的类不应实现 `IEquatable`。

对于您的特定类,我建议由于只有 65,536 个可能的不同实例,您应该简单地存储一个Integer标识使用哪种位组合的 ,比较它 in Equals,然后将其返回为GetHashCode.

于 2012-10-10T23:56:26.507 回答