Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I want to implement EqualityComparer<T> for feature classes so that I can stuff them into a Dictionary or HashSet.

For motivation, say that I am looping over many IFeature objects which belong to different feature classes, and I want to set field values for each. FindField is inefficient to perform inside of a loop. If I have a Dictionary<IFeatureClass, Dictionary<string, int>> to give me the index of a given field, this operation would be much faster.

So, how does one uniquely identify a feature class object? The AliasName property is not unique. The IName object should be, but I'm not sure how to compare them, or how to hash them. Is IDataset.Name unique to each feature class? If it is, it must include the full data path, right?

Thanks!

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

Well, all things being equal, I would normally point out that your .NET dictionary is implemented as a tree, and if it were balanced, (otherwise the time complexity would be worse) the time complexity would be O(log n) while ESRI's FindField is internally implemented as a Hash table, and thus a time complexity of O(1) which is much better.

Of course I said all things being equal. And in this case, they are not, because you are using .NET an there is the issue of context switching and marshalling which is better explained as the first item of a previous related post that I did about ArcObjects performance.

My recommendation to you is to switch to .NET Hash tables instead of the Dictionaries.

OK, moving on.

To answer your second question, under non-managed conditions(i.e not Java or .NET) the answer is super simple, just compare pointers of objects! The unique-instancing model (per thread) of the factory pattern used by the GeoDatabase guarantees that the objects will be the same.

For .NET, its multi-generation memory model throws this technique out of the window - from the .NET side.

Nevertheless, for comparing pointer equality of most ArcObjects, you can use IClone's IsIdentical method which basically compares memory addresses in COM land.

So what is the solution for the FeatureClass case (that AFAIK, doesn't implement IClone). You have to take the long route :(

Use IDataset::name on the FC to get a fully qualified name, and then go to the parent Workspace and verify its connection properties to make sure the db is the same. Funny enough, this also covers an interesting Versioning case (Two FCs that are connected to the same DB, but are connected to different versions of the same FC).

Update: My original observation about .NET Dictionaries is incorrect. Apparently, they are implemented as hash tables as Scott points out :)

share|improve this answer
    
Actually, the .NET Dictionary class is implemented as a Hash Table, and thus looking up an item by key is O(1). See the Remarks section here. Because Esri cautions against using it within loops, I've alwyas assumed that FindField is O(n). How did you learn that it was O(1)? Is Esri just worried about the overhead of a hash table lookup? So IClone.IsIdentical() tests for reference equality? Does it give different results than Object.ReferenceEquals()? If the .NET call is unreliable for COM objects, I have some refactoring to do. –  Scott B Oct 19 '11 at 20:19
    
@ScottB Oh, it goes to show my ignorance of certain .NET data structures. Going to edit my answer :) –  Ragi Yaser Burhum Oct 19 '11 at 22:04
1  
FindField is O(1) + COM overhead. How do I know? I worked at the GeoDatabase team for several years maintaining and extending this code. ESRI is worried that you are paying unnecessary COM marshaling price. AFAIK Object.ReferenceEquals is testing for equality of reference of the .NET wrapper, which is very different than the address of the COM object itself (which is tested by IsIdentical). Unless the ESRI shipped wrappers have been modified to use IClone::IsIdentical (they could, I do not know though), they would have different behavior. –  Ragi Yaser Burhum Oct 19 '11 at 22:14
    
Thanks Ragi! This answer, and your insightful performance post here, are the most helpful ArcObjects information I've read this year. And now I further regret turning down my offer from Esri for a spot on the GeoDatabases team; I might have been as well informed as you :) –  Scott B Oct 19 '11 at 22:21
add comment

If you want to work with datasets you can implement IEnumDatasetName to walk through all of your feature classes. IDataset.Name will be unique, but you will have to get the full path - if all of your data is stored in the same place this is simple, if not, you'll have to do a bit of work to grab the full paths first.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.