вызов метода с двумя одинаковыми параметрами возвращает два разных результата


У меня есть простой проект, использующий шаблон MVC, ET и WCF. Он использует Дейкстру для поиска путей между городами. Это и есть сам класс.

Однако при вызове FindPathFromCityToCity() с двумя одинаковыми списками в объекте map, такими же from и to, когда он находится в обычном консольном приложении, он возвращает желаемый результат. Однако, при использовании из WCF, он терпит неудачу на строке 39 с исключением System.Collections.Generic.KeyNotFoundException.

Чтобы проверить, является ли мой ввод неверным, я добавил эту запись в файл txt (строка 17-27) и вот что получается (TL; DR-оба совершенно одинаковы):

Консоль:

COUNT: 14 - RANGE 120
FROM: Aalborg - TO: Copenhagen
C: Frederikshavn - E: 2 - T: BLL.BatteryCenter
C: Aalborg - E: 6 - T: BLL.BatteryCenter
C: Hobro - E: 4 - T: BLL.BatteryCenter
C: Randers - E: 6 - T: BLL.BatteryCenter
C: Viborg - E: 8 - T: BLL.BatteryCenter
C: Aarhus - E: 8 - T: BLL.BatteryCenter
C: Herning - E: 6 - T: BLL.BatteryCenter
C: Vejle - E: 8 - T: BLL.BatteryCenter
C: Kolding - E: 6 - T: BLL.BatteryCenter
C: Odense - E: 6 - T: BLL.BatteryCenter
C: Aabenraa - E: 2 - T: BLL.BatteryCenter
C: Koge - E: 4 - T: BLL.BatteryCenter
C: Copenhagen - E: 2 - T: BLL.BatteryCenter
C: Soro - E: 4 - T: BLL.BatteryCenter

WCF:

COUNT: 14 - RANGE 120
FROM: Aalborg - TO: Copenhagen
C: Frederikshavn - E: 2 - T: BLL.BatteryCenter
C: Aalborg - E: 6 - T: BLL.BatteryCenter
C: Hobro - E: 4 - T: BLL.BatteryCenter
C: Randers - E: 6 - T: BLL.BatteryCenter
C: Viborg - E: 8 - T: BLL.BatteryCenter
C: Aarhus - E: 8 - T: BLL.BatteryCenter
C: Herning - E: 6 - T: BLL.BatteryCenter
C: Vejle - E: 8 - T: BLL.BatteryCenter
C: Kolding - E: 6 - T: BLL.BatteryCenter
C: Odense - E: 6 - T: BLL.BatteryCenter
C: Aabenraa - E: 2 - T: BLL.BatteryCenter
C: Koge - E: 4 - T: BLL.BatteryCenter
C: Copenhagen - E: 2 - T: BLL.BatteryCenter
C: Soro - E: 4 - T: BLL.BatteryCenter

Может ли кто-нибудь увидеть какую-либо причину для этого?


Редактировать:

Я сделал дальнейшие тесты, распечатав все возможные объекты с этим фрагментом и Нет никакой разницы в объектах (кроме хэша, конечно):

using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:logcheck.txt", true))
{
    foreach (var m in map.Stations)
    {
        file.WriteLine(" --- {0} - {1} - {2} - {3} --- ", m.name, m.Edgelist.Count, m.GetType(), m.GetHashCode());
        foreach(var e in m.Edgelist)
        {
            file.WriteLine();
            file.WriteLine(" # {0} - {1} - {2} - {3}", e.BatteryStation.name, e.BatteryStation1.name, e.distance, e.edgeID);
            file.WriteLine(" + {0} - {1} - {2}", e.BatteryStation.GetType(), e.BatteryStation.stationID, e.BatteryStation.GetHashCode());
            file.WriteLine(" - {0} - {1} - {2}", e.BatteryStation1.GetType(), e.BatteryStation1.stationID, e.BatteryStation1.GetHashCode());
        }
        file.WriteLine();
   }
}
1 2

1 ответ:

Все это зависит от механики объекта BatteryCenter.

Вызывающий код передает его в качестве параметра, а функция использует его в качестве ключа в карте.

Вы переопределили функции Equals и GetHashCode на BatteryCenter?

Если нет, то поиск по словарю будет искать этот точный объект. Не BatteryCenter со всеми одинаковыми полями, а объект с одной и той же ссылкой.

Клиент WCF будет передавать эквивалент, но тем не менее разные BatteryCenter, которые словарь не может найти.

После добавления переопределений для BatteryCenter.Equals и BatteryCenter.GetHashCode это, вероятно, сработает.

Например

public override int GetHashCode() 
{
     return this.stationID.GetHashCode() ^ this.name.GetHashCode();
}

public override bool Equals(Object obj) 
{
     if(Object.ReferenceEquals(this, obj))
     {
          return true;
     }
     BatteryStation other = obj as BatteryStation;
     if(Object.ReferenceEquals(other, null))
     {
         return false;
     }
     return ((this.stationID == other.stationID) && (this.name == other.name));
}