invoking method with two same parameters returns two different results

145 views Asked by At

I have a simple project, using MVC pattern, ET and WCF. It uses Dijkstra to find paths between cities. This is the class itself.

However, when calling FindPathFromCityToCity() with two same lists in the map object, same from and to, when it's on a normal console application it returns the desired result. However, when used from WCF, it fails on line 39 with exception System.Collections.Generic.KeyNotFoundException.

In order to check whether if my input is incorrect I added that writing to a txt file (line 17 to 27) and this is what it results (TL;DR - both are exactly the same):

Console:

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

Can someone see any reason for that to happen?


EDIT:

I did further tests, printing everything possible of the objects with this snippet and there is no difference in the objects (except hash of course):

using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\log\check.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

There are 1 answers

1
Andrew Shepherd On BEST ANSWER

This all hinges on the mechanics of the BatteryCenter object.

The calling code is passing it in as a parameter, and the function is using it as a key in the map.

Have you overridden the functions Equals and GetHashCode on BatteryCenter?

If not, then the dictionary lookup will be searching for that exact object. Not a BatteryCenter with all of the same fields, but the object with the same reference.

The WCF client would be passing in an equivalent but nonetheless different BatteryCenter, which the dictionary is failing to find.

Once you add overrides for BatteryCenter.Equals and BatteryCenter.GetHashCode this would probably work.

eg

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