2016-04-28 2 views
1

У меня есть структура IntVector2, которая имеет свойство X и Y. Оператор + перекрывается сList.Contains не работает, как ожидалось, с помощью настраиваемого аргумента struct

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

При использовании этого в списке с содержит метод, он не проверяет общую стоимость добавления, но только переменная «текущая»

if (visited.Contains(current + dir)) 
    continue; 

Что на самом деле здесь?

Редактировать: Вот скриншот значений переменных и объявление переменной, которое равно тому, что я ожидаю от значения, которое содержится для проверки.

https://dl.dropboxusercontent.com/u/30062610/Brokestuff.png

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; 
    } 

Редактировать 3: Даже используя переменную newstuff, которая имеет другое значение с самого начала, продолжается. Я не уверен, что это может сделать. Мои равны переопределяют только проверки, если X и Y равны и возвращают true, если это так.

Вот совокупность кода IntVector2: http://pastebin.com/ic108SeF

Редактировать 4: Я изменил оператор + к:

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

И проблема все еще сохраняется.

+0

Почему вы изменяете 'значение1'? –

+0

Вы изменили определение 'Equals'? '((1,1) + (2,2)). Равные (3,3)' дают для меня «истину». – Rob

+0

Я решил изменить первый аргумент со значением второго. Должен ли я изменить его, чтобы вернуть новый IntVector2 с новой суммой вместо изменения первой? – user3010006

ответ

1

У вас есть опечатка в методе Equals:

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

Ошибочный код сравнивает this к this, поэтому она всегда возвращает true.

+0

Думаю, что я получил его, пытаясь сейчас. Благодаря! – user3010006

+0

Работает отлично, хорошо поймать :) Спасибо! – user3010006

+0

Добро пожаловать! –

-1

С вашим текущим кодом Содержит не может определить равенство для двух экземпляров структуры. Если вы переопределите IntVector2 :: GetHashCode, чтобы идентичные значения возвращали один и тот же хэш, он должен начать работать так, как вы ожидаете.

+0

'List' не использует' GetHashCode'. – Rob

+0

Список не может, но Object.Equals делает, а List :: Contain использует Object.Equals, если не предусмотрен альтернативный компаратор. –

+0

Это, к сожалению, неверно. Вы можете поставить точку останова на 'Equals', если вы не уверены. По умолчанию 'Object.Equals' использует' Object.ReferenceEquals' – Rob

1

Хорошо, я считаю, что я понял вашу проблему.

Ваши равно переопределения не переопределение, то есть в коде, как:

public bool Equals(IntVector2 other) { 
     return (X == other.X) && (Y == other.Y); 
    } 

Что вы делали там добавили метод под названием Равно. Таким образом, вы фактически перегрузили метод Actual equals, который вам нужно переопределить. Содержит не будет вызывать метод equals, потому что он вызывает исходный, который принимает объект.

И когда вы переопределяете метод равных справа, вы должны в хорошей практике реализовать GetHashCode и использовать GetHashCode, чтобы определить, действительно ли объекты действительно равны.

В вашем случае у вас не будет проблемы с переопределением GetHashCode, так как вы основываете eqaulity на два целых числа, одинаковые в другой копии IntVector2, и вы не можете действительно вычислить целочисленный хеш-код для этого как X и Y - целые числа.Если вы выполнили реализацию GetHashCode здесь, вы можете столкнуться с ошибками позже, если у вас есть большое количество из них, вы можете получить коды хеша оверки, которые не являются равными объектами.

Вот обновленный код, который вы должны попробовать.

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); 
    } 
} 
+0

Человек, чтобы замедлить :( –

+0

А я ушел с неправильной ссылки pastebin, я смотрел на другую, но эта опечатка тоже была там. –

+0

Спасибо Ryios. Хотел бы я отметить, что вы оба правы! noob, чтобы переместить тоже. :(Хорошо поймать на этом, хотя! – user3010006