Determine if two arrays are structurally equal in C# .NET

Two arrays are said to be structurally equal if they contain the same elements in the same order. Whether or not two elements are the same depends on how you define equality for your custom types. Equality for primitive types, like integers, is more or less straightforward but you’ll need to declare in code what is meant by equality for reference types.

We’ve looked at a couple of strategies to do so on this blog and here we’ll re-use the topic of implementing the IEqualityComparer of T interface.

The non-generic IStructuralEquatable interface has an equals method that accepts an object to compare with and another object which implements the non-generic IEqualityComparer interface. This is an important distinction as implementing the generic IEqualityComparer interface won’t be enough for structural equality. We’ll need to derive from the EqualityComparer base class which implements both the generic and non-generic version of IEqualityComparer. If you try to run the below example with a generic IEqualityComparer of T instance then you’ll get a compiler error.

Note that structural equality is not available for all collection types. Currently only arrays and tuples support it, i.e. they can be cast to type IStructuralEquatable. However, as List objects can be easily converted into arrays that’s not really an obstacle.

Consider the following Triangle class:

public class Triangle
	public double BaseSide { get; set; }
	public double Height { get; set; }

Let’s say that two triangles are equal if their bases and heights are the same. We’ll implement our equality comparer accordingly. As noted above we need to derive from the EqualityComparer

public class TriangleSideEqualityComparer : EqualityComparer<Triangle>
	public override bool Equals(Triangle x, Triangle y)
		return (x.BaseSide == y.BaseSide && x.Height == y.Height);

	public override int GetHashCode(Triangle obj)
		return (obj.BaseSide.GetHashCode() * obj.Height.GetHashCode());

Now consider the following collections:

List<Triangle> triangleListOne = new List<Triangle>()
	new Triangle(){BaseSide = 2, Height = 4},
	new Triangle(){BaseSide = 4, Height = 5},
	new Triangle(){BaseSide = 5, Height = 9},
	new Triangle(){BaseSide = 3, Height = 8}

List<Triangle> triangleListTwo = new List<Triangle>()
	new Triangle(){BaseSide = 2, Height = 4},
	new Triangle(){BaseSide = 4, Height = 5},
	new Triangle(){BaseSide = 5, Height = 9},
	new Triangle(){BaseSide = 3, Height = 8}

The two lists are clearly structurally equal as they store equal Triangle instances where the triangles appear in the same order. Here’s a possible solution to the problem:

IStructuralEquatable equatableOne = triangleListOne.ToArray();
bool areStructurallyEqual = equatableOne.Equals(triangleListTwo.ToArray(), new TriangleSideEqualityComparer());

areStructurallyEqual will be true. As soon as we change just a single parameter in any of the triangles then this function will result in false.

View all various C# language feature related posts here.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

HarsH ReaLiTy

A Good Blog is Hard to Find

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog


Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: