Skip to content

Add HashSet.CreateSetComparer(comparer) #19644

@JonHanna

Description

@JonHanna

2nd API review iteration [TODO]

TODO - Fill the new API proposal here please, with summary of the troubles we have found during code review of the 1st API review iteration.

1st API review iteration [approved] - for context

Originally approved in https://github.com/dotnet/corefx/issues/14416#issuecomment-279797190

1. Addition of new Method

namespace System.Collections.Generic
{
    public class HashSet<T>
    {
        public static IEqualityComparer<HashSet<T>> CreateSetComparer(
            IEqualityComparer<T> comparer);
    }
}

This method will return an IEqualityComparer<HashSet<T>> that uses the IEqualityComparer<T> passed to it in comparing elements to determine equality of hash-sets.

The comparer returned will consider two sets equal iff for each element in either there is an element in the other that comparer considers equal to it.

Optimised paths may only be taken if they give the same result as this.

If comparer is null, the method will treat this as if EqualityComparer<T>.Default had been passed to it.

The comparer will produce a hash code for sets as follows:

  1. If the set is null the hash code is 0.
  2. Otherwise start with a seed value. For each value that comparer considers distinct, exclusive-or comparer.GetHashCode(element) with it. (The use of exclusive-or allows this algorithm to be agnostic to element order).

2. Obsolescence of Current CreateSetComparer Method

```C# namespace System.Collections.Generic { public class HashSet { [System.Obsolete("This method can produce inconsistent results. Use CreatSetComparer(IEqualityComparer")] public static IEqualityComparer> CreateSetComparer(); } } ```

The existing CreateSetComparer method has a minor design and major implementation issue. The design issue is that it lacks the ability to select the IEqualityComparer<T> to use. If this was the only problem it could work as an overload equivalent to CreateSetComparer(null) but it also has implementation flaws resulting in a non-commutative Equals() and disagreement between Equals() and GetHashCode(). However fixing it would break some cases that it can (in disagreement with how it is specified) serve to usefully determine set-equality of two sets in respect of their own comparers, if those comparers are the same. See #18931

Since it can't be fixed without considerable breaks, and both the specified behaviour and the other type of comparison it sometimes makes are offered by the new method (with a clear way of indicating which is wanted), this method should be obsoleted. (Fixing it to behave as specified could be considered after it has been obsolete for some time, as an alternative to deleting it).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions