Finding unconnected sets
Since we are talking about sets, it's probably better to use collection types that represent a set: HashSet&lt;T&gt; and ISet&lt;T&gt;.

Another improvement you can make is to keep track of the boxes you've added to current set at the last iteration (horizon of your expansion), and try to match candidate boxes only with them.

Note that resulting solution doesn't use the knowledge about box matching logic, so it might be a good idea to extract the interface that defines the connection between elements (i.e. a method that checks for the presence of link between nodes).

As a result I've got the following solution:

public interface IConnected&lt;in T&gt;
{
    bool IsConnectedTo(T other);
}

public class Box: IConnected&lt;Box&gt;
{
    ....

    public bool IsConnectedTo(Box other)
    {
        return Overlaps(other);
    }
}


And the FindUnconnectedSets:

public static List&lt;ISet&lt;T&gt;&gt; FindUnconnectedSets&lt;T&gt;(IEnumerable&lt;T&gt; boxes) where T : IConnected&lt;T&gt;
{
    var remainingBoxes = new HashSet&lt;T&gt;(boxes);
    var unconnectedSets = new List&lt;ISet&lt;T&gt;&gt;();

    while (remainingBoxes.Count &gt; 0)
    {
        var newBoxes = new[] { remainingBoxes.First() }; //on each iteration will contain newly added boxes to current set
        var currentSet = new HashSet&lt;T&gt;();
        unconnectedSets.Add(currentSet);

        do
        {
            currentSet.UnionWith(newBoxes);
            remainingBoxes.ExceptWith(newBoxes);
            newBoxes = remainingBoxes
                .Where(remainingBox =&gt; newBoxes.Any(setBox =&gt; setBox.IsConnectedTo(remainingBox)))
                .ToArray();
        } while (newBoxes.Length &gt; 0);
    }

    return unconnectedSets;
}