What interfaces must I implement to make a List<T> or Dictionary<T> concatenate two values as a key

345 Views Asked by At

I need to make my custom object work correctly in a Dictionary, List, etc... so that I can change properties of the object, and allow it to be resorted, and not orphaned.

The last time I attempted overriding GetHashCode(), I orphaned objects when I added the object to the dictionary, made a change to the object (which changed GetHashCode) which somehow caused Dictionary to not properly dispose of the object from memory.

Question

Can someone explain:

  • What interfaces and interfaces I need to override in TrustedEntityReference to concatenate int and TrustedEntity work correctly in a sorted dictionary?

  • What values must never change with regard to what is used in a .NET dictionary object, or else risking orphaning the object? (Example, changing the emitted hashcode of an object may cause GC issues with a dictionary)

Here is a current sample object that I'm working on.

namespace Model
{
    public class TrustedEntity
    {
        public TrustedEntity()
        {
            this.BackTrustLink = new List<TrustedEntityReference>();
            this.ForwardTrustLink = new List<TrustedEntityReference>();
        }

        public List<TrustedEntityReference> BackTrustLink { get; set; }

        public string EntryName { get; set; }

        public List<TrustedEntityReference> ForwardTrustLink { get; set; }
    }


    // This is the object I want to be treated as a "key" in the above List<T>
    // I want a duplicate object exception to occur if a duplicate TrustedEntityReference is inserted into trustedEntity.BackTrustLink or trustedEntity.ForwardTrustLink

    public class TrustedEntityReference   
    {
        public int HierarchyDepth { get; set; }
        public TrustedEntity TrustedEntity {get; set; }


    }
}
3

There are 3 best solutions below

0
On

No interface is required to use List or Dictionary

TKey cannot change (otherwise you will not be able to find the entry in the Dictionary since you will be looking for the wrong key).

Edit:
Looks like I missed the TKey type.

Dictionary requires an equality implementation to determine whether keys are equal. You can specify an implementation of the IEqualityComparer generic interface by using a constructor that accepts a comparer parameter; if you do not specify an implementation, the default generic equality comparer EqualityComparer.Default is used. If type TKey implements the System.IEquatable generic interface, the default equality comparer uses that implementation.

I expect this means TrustedEntityReference should implement the IEqualityComparer interface (though I would implement ICompariable at the same time).
You could also specifiy your own using the Dictionary(IEqualityComparer) Constructor.

It is essential that the methods in these interfaces always return the same value, even if the value of the object has changed.

http://msdn.microsoft.com/en-us/library/ms132072.aspx

Please let me know if you need more.

0
On

So the main things are to override GetHashCode and Equals (excluding the sorting stuff). The next thing you want to make sure of is that once you have returned a value from GetHashCode, you need to return the same value even for the lifetime of that object, even if the values it's generated from are modified.

For sorting, you should just need IComparable for the default comparer, or you can give it your own Comparer instance.

0
On

You don't actually need to do anything special at all, provided that duplicate data is not a problem (either because it doesn't happen, something else is enforcing it, or because you want it in there multiple times).

Specifically, as per this answer, you can use any object and it only checks reference equality. Is this object the same object? A different object with the same data will be different, but the same object, even if you've changed the data, will be the same.

So for your example, if you populated your List<TrustedEntityReference>'s from the same initial data, you wouldn't have a problem. If they each load their own set of data, this won't help.