Feature Identity

519
4
Jump to solution
07-11-2017 06:03 AM
JensBuchta
Occasional Contributor

This code fails, f1 and f2 are not considered to be equal:

var gdb = await Geodatabase.OpenAsync(@"mytest.geodatabase");
var ft = gdb.GeodatabaseFeatureTables.First();
var f1 = (await ft.QueryFeaturesAsync(new QueryParameters {WhereClause = "OBJECTID=1"})).Single();
var f2 = (await ft.QueryFeaturesAsync(new QueryParameters {WhereClause = "OBJECTID=1"})).Single();
Assert.AreEqual(f1, f2);

I really wonder, if this is intended behavior or not.

I'd say, it's really good that we are not getting the same object here, this helps avoiding memory leaks a lot. But shouldn't two objects of the same type with the same properties be considered equal?

0 Kudos
1 Solution

Accepted Solutions
dotMorten_esri
Esri Frequent Contributor

This is intended. Every time you pull a row out of a table, it's converted into a feature object. Thus the reference would never be equal. The behavior matches what you see with any other database queries in .NET (and most if not all other platforms where the data storage isn't in-memory)

View solution in original post

4 Replies
dotMorten_esri
Esri Frequent Contributor

This is intended. Every time you pull a row out of a table, it's converted into a feature object. Thus the reference would never be equal. The behavior matches what you see with any other database queries in .NET (and most if not all other platforms where the data storage isn't in-memory)

JoeHershman
MVP Regular Contributor

You would have to implement your own IEqualityComparer to define what "Equal" means in this case.  Your Assert would then need to be .IsTrue(A.Equals(B, MyComparer).

internal class FeatureComparer : IEqualityComparer<Feature>
{
     public bool Equals(Feature x, Feature y)
     {
          try
          {
               if ( x == null ) return false;
               if ( y == null ) return false;

               Field xField = x.FeatureTable.Fields.First(f => f.FieldType == FieldType.GlobalID);
               Field yField = y.FeatureTable.Fields.First(f => f.FieldType == FieldType.GlobalID);

               return x.GetAttributeValue(xField).Equals(y.GetAttributeValue(yField));
          }
          catch
          {
               return false;
          }
     }

     public int GetHashCode(Feature obj)
     {
          return obj.GetHashCode();
     }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JensBuchta
Occasional Contributor

Wow, that got fast responses :)

@Morten: I didn't know, other database queries in .NET behave the same. Thanks for sharing background information along with your answer!

@Joe: Thanks for your suggestion. I think, in case of an own comparer, the GetHashCode method should be implemented based on the same values as well. At least, that's the case if anyone decides to override Equals within the object itself.

0 Kudos
JoeHershman
MVP Regular Contributor

That would probably be the better approach.  But I had no intention of using as a Dictionary/Hash key so took the lazy approach.

0 Kudos