views:

53

answers:

1

I've noticed these two interfaces, and several associated classes, have been added in .NET 4. They seem a bit superfluous to me; I've read several blogs about them, but I still can't figure out what problem they solve that was tricky before .NET 4.

What use are IStructuralEquatable and IStructuralComparable?

+5  A: 

All types in .NET support the Object.Equals() method which, by default, compares two types for reference equality. However, sometimes, it also desirable to be able to compare two types for structural equality.

The best example of this is arrays, which with .NET 4 now implement the IStructuralEquatable interface. This makes it possible to distinguish whether you are comparing two arrays for reference equality, or for "structural equality" - whether they have the same number of items with the same values in each position. Here's an example:

int[] array1 = new int[] { 1, 5, 9 };
int[] array2 = new int[] { 1, 5, 9 };

// using reference comparison...
Console.WriteLine( array1.Equals( array2 ) ); // outputs false

// now using structural comparison...
IStructuralEquatable eqArray1 = array1;
Console.WriteLine( eqArray1.Equals( array2 ) ); // outputs true

Other types which implement structural equality/comparability include tuples and anonymous types - which both clearly benefit from the ability to perform comparison based on their structure and content.

A question you didn't ask is:

Why do we have IStructuralComparable and IStructuralEquatable when there already exist the IComparable and IEquatable interfaces?

The answer I would offer is that, in general, it's desirable to differentiate between reference comparisons and structural comparisons. It's normally expected that if you implement IEquatable<T>.Equals you will also override Object.Equals to be consistent. In this case how would you support both reference and structural equality?

LBushkin
Why can't you just specify an `IEqualityComparer` yourself that does this? What does the `IStructuralEquatable` interface add to this?
thecoop
@thecoop: There's two reasons. First, not all types implement an overload of `Equals` that accepts an `IEqualityComparer` - Array is an example, IIRC. Second, supplying an equality comparer is nice, but what if you want to express the fact that a certain method requires two objects that can be structurally compared? Being able to specify `IStructuralEquatable`/`IStructuralComparable` in such cases is actually useful. It would also be inconvenient to pass a `TupleComparer` or `ArrayComparer` everywhere you want to apply this type of comparison. The two approaches are not mutually exclusive.
LBushkin
@LBushkin: How do such comparators relate to things like Dictionary and other collections? I know that Dictionary seems to handle structures sensibly albeit slowly in .Net 2.0; does .Net 4.0 (or 3.x for that matter) allow arrays to be conveniently stored in Dictionary (using the array contents as the key)?
supercat
@supercat: I don't believe you can use arrays as keys in .NET 4 any more easily than you could in previous versions. As far as I know, neither Dictionary nor other keyed collection classes use the `IStructuralEquatable` interface. But this would be easy enough to verify with some test code.
LBushkin