C# List.Contains在自定义结构参数中无法正常工作

C# List.Contains在自定义结构参数中无法正常工作,c#,struct,collections,value-type,C#,Struct,Collections,Value Type,我有一个结构IntVector2,它有X和Y属性。+运算符被替换为 public static IntVector2 operator +(IntVector2 value1, IntVector2 value2) { value1.X += value2.X; value1.Y += value2.Y; return value1; } 在列表中使用contains方法时,它不会检查加法的总值,只检查变量“current” 这里到底发生了什么 编辑:这里有一个变量值的

我有一个结构IntVector2,它有X和Y属性。+运算符被替换为

public static IntVector2 operator +(IntVector2 value1, IntVector2 value2)
{
    value1.X += value2.X;
    value1.Y += value2.Y;
    return value1;
}
在列表中使用contains方法时,它不会检查加法的总值,只检查变量“current”

这里到底发生了什么

编辑:这里有一个变量值的屏幕截图,以及一个变量声明,它等于我希望检查的contains值

Edit2:这是该方法的完整代码,它是A*寻路算法的开始,该算法从起始向量查找结束向量

                    public Path Pathfind(IntVector2 start, IntVector2 end)
    {
        Queue<IntVector2> fillQueue = new Queue<IntVector2>();
        List<IntVector2> visited = new List<IntVector2>();
        fillQueue.Enqueue(start);
        IntVector2 current;
        while (fillQueue.Count > 0)
        {
            current = fillQueue.Dequeue();
            foreach (IntVector2 dir in Directions)
            {
                if (GetCell(current + dir).IsWall)
                    continue;
                else
                {
                    IntVector2 newstuff = current + dir;
                    if (visited.Contains(current + dir))
                        continue;
                    if ((current + dir) == end)
                    {
                        //We've reached the target, traceback the path and return it.
                    }
                    visited.Add(current);
                    fillQueue.Enqueue(current + dir);
                }
            }
        }
        return null;
    }

问题仍然存在。

对于当前代码,Contains无法确定两个结构实例的相等性。如果您重写IntVector2::GetHashCode,以便相同的值返回相同的哈希值,那么它应该按照您的预期开始工作

您在
Equals
方法中有输入错误:

public override bool Equals(object obj)
{ 
    if (obj is IntVector2)
    {
        return Equals((IntVector2)this); // <-- "this" should be "obj"
    }
}
public override bool Equals(对象对象对象)
{ 
if(obj为IntVector2)
{

返回等于((IntVector2)this);//好的,我想我解决了你的问题

您的equals替代不是替代,您在代码中的替代形式为:

    public bool Equals(IntVector2 other) { 
        return (X == other.X) && (Y == other.Y); 
    }
您在那里所做的是添加了一个名为Equals的方法。因此,实际上您已经重载了需要重写的实际Equals方法。Contains不会调用您的Equals方法,因为它调用了接受对象的原始方法

当您重写right equals方法时,在良好的实践中,您应该实现GetHashCode并使用GetHashCode来确定对象是否真正相等

在您的情况下,不重写GetHashCode不会有任何问题,因为您是基于IntVector2的另一个副本中相同的两个整数来计算eqaulity的,并且您不能真正为此计算整数哈希代码,因为X和Y都是整数。如果您在这里执行GetHashCode实现,如果您有一个较大的nu,您可能会在以后遇到错误其中的一些可能会导致重复哈希代码,这些代码是不相等的对象

以下是您应该尝试的更新代码

public struct IntVector2
{
    public int X { get; set; }
    public int Y { get; set; }

    public static IntVector2 operator +(IntVector2 value1, IntVector2 value2)
    {
        value1.X += value2.X;
        value1.Y += value2.Y;
        return value1;
    }

    public override int GetHashCode()
    {
        //overrode this to get rid of warning
        return base.GetHashCode();
    }

    //This equals get's called, notice the override keyword
    public override bool Equals(object obj)
    {
        if (obj is IntVector2)
        {
            IntVector2 vObj = (IntVector2)obj;
            return vObj.X == this.X && vObj.Y == this.Y;           
        }
        return false;
    }

    //This won't get called, it's not part of the framework, this is adding a new overload for equals that .Net won't know about.
    public bool Equals(IntVector2 other)
    {
        return (X == other.X) && (Y == other.Y);
    }

    public override string ToString()
    {
        return string.Format("{ value1: {0}, value2: {0} }", X, Y);
    }
}

您为什么要修改
value1
?您是否更改了
Equals
定义?
((1,1)+(2,2))。Equals(3,3)
为我生成
true
。我想用第二个参数的值修改第一个参数是可行的。我是否应该将其更改为返回一个新的IntVector2和新的总计,而不是修改第一个参数?@user3010006然后在那里放置一个断点并对其进行调试-因为它确实适用于默认的
Equals
实现另外,请向我们展示
currentDir
dir
的值,以及您希望在
visted
@user3010006中看到的内容。如果我们都看过了,代码肯定会起作用。我想visted中的实际内容与您的预期不符。
List
不使用
GetHashCode
.List可能没有,但是Object.Equals有,并且List::Contain使用Object.Equals,除非提供了可选的比较器。不幸的是,这是不正确的。如果您不确信,您可以在
Equals
上设置断点。默认的
对象.Equals
使用
对象。ReferenceEquals
我想知道了,现在就尝试。谢谢!Also你的方法名是contains而不是equals。但我得到了:3Ah我走错了pastebin链接,我看到了另一个,但这个输入错误也在那里。谢谢你。我希望我能把你们两个都标记正确!我的帐户也无法向上投票(不过这很好!@user3010006:您应该在您的结构上实现
IEquatable
接口,以便
包含
调用
等于(IntVector2 other)
直接重载,而不必对值进行装箱和取消装箱。
    public bool Equals(IntVector2 other) { 
        return (X == other.X) && (Y == other.Y); 
    }
public struct IntVector2
{
    public int X { get; set; }
    public int Y { get; set; }

    public static IntVector2 operator +(IntVector2 value1, IntVector2 value2)
    {
        value1.X += value2.X;
        value1.Y += value2.Y;
        return value1;
    }

    public override int GetHashCode()
    {
        //overrode this to get rid of warning
        return base.GetHashCode();
    }

    //This equals get's called, notice the override keyword
    public override bool Equals(object obj)
    {
        if (obj is IntVector2)
        {
            IntVector2 vObj = (IntVector2)obj;
            return vObj.X == this.X && vObj.Y == this.Y;           
        }
        return false;
    }

    //This won't get called, it's not part of the framework, this is adding a new overload for equals that .Net won't know about.
    public bool Equals(IntVector2 other)
    {
        return (X == other.X) && (Y == other.Y);
    }

    public override string ToString()
    {
        return string.Format("{ value1: {0}, value2: {0} }", X, Y);
    }
}