public sealed record SelectionKey(string? Residing, string? Visiting = null, string? Centre = null, string? Category = null, string? SubCategory = null)
{
    public static IEqualityComparer<SelectionKey> ResidingVisitingComparer { get; } = new ResidingVisitingEqualityComparer();
    public static IEqualityComparer<SelectionKey> CentreComparer { get; } = new CentreEqualityComparer();
    public static IEqualityComparer<SelectionKey> CategoryComparer { get; } = new CategoryEqualityComparer();

    public bool Equals(SelectionKey? other)
    {
        if (other is null) return false;
        if (ReferenceEquals(this, other)) return true;

        return string.Equals(Residing, other.Residing, StringComparison.OrdinalIgnoreCase) &&
               string.Equals(Visiting, other.Visiting, StringComparison.OrdinalIgnoreCase) &&
               string.Equals(Centre, other.Centre, StringComparison.OrdinalIgnoreCase) &&
               string.Equals(Category, other.Category, StringComparison.OrdinalIgnoreCase) &&
               string.Equals(SubCategory, other.SubCategory, StringComparison.OrdinalIgnoreCase);
    }

    public override int GetHashCode()
    {
        var hashCode = new HashCode();
        hashCode.Add(Residing, StringComparer.OrdinalIgnoreCase);
        hashCode.Add(Visiting, StringComparer.OrdinalIgnoreCase);
        hashCode.Add(Centre, StringComparer.OrdinalIgnoreCase);
        hashCode.Add(Category, StringComparer.OrdinalIgnoreCase);
        hashCode.Add(SubCategory, StringComparer.OrdinalIgnoreCase);
        return hashCode.ToHashCode();
    }

    private sealed class ResidingVisitingEqualityComparer : IEqualityComparer<SelectionKey>
    {
        public bool Equals(SelectionKey? x, SelectionKey? y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (x is null) return false;
            if (y is null) return false;
            //if (x.GetType() != y.GetType()) return false;

            return string.Equals(x.Residing, y.Residing, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(x.Visiting, y.Visiting, StringComparison.OrdinalIgnoreCase);
        }

        public int GetHashCode(SelectionKey obj)
        {
            var hashCode = new HashCode();
            hashCode.Add(obj.Residing, StringComparer.OrdinalIgnoreCase);
            hashCode.Add(obj.Visiting, StringComparer.OrdinalIgnoreCase);
            return hashCode.ToHashCode();
        }
    }
    private sealed class CentreEqualityComparer : IEqualityComparer<SelectionKey>
    {
        public bool Equals(SelectionKey? x, SelectionKey? y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (x is null) return false;
            if (y is null) return false;
            //if (x.GetType() != y.GetType()) return false;

            return string.Equals(x.Residing, y.Residing, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(x.Visiting, y.Visiting, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(x.Centre, y.Centre, StringComparison.OrdinalIgnoreCase);
        }

        public int GetHashCode(SelectionKey obj)
        {
            var hashCode = new HashCode();
            hashCode.Add(obj.Residing, StringComparer.OrdinalIgnoreCase);
            hashCode.Add(obj.Visiting, StringComparer.OrdinalIgnoreCase);
            hashCode.Add(obj.Centre, StringComparer.OrdinalIgnoreCase);
            return hashCode.ToHashCode();
        }
    }
    private sealed class CategoryEqualityComparer : IEqualityComparer<SelectionKey>
    {
        public bool Equals(SelectionKey? x, SelectionKey? y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (x is null) return false;
            if (y is null) return false;
            //if (x.GetType() != y.GetType()) return false;

            return string.Equals(x.Residing, y.Residing, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(x.Visiting, y.Visiting, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(x.Centre, y.Centre, StringComparison.OrdinalIgnoreCase) &&
                   string.Equals(x.Category, y.Category, StringComparison.OrdinalIgnoreCase);
        }

        public int GetHashCode(SelectionKey obj)
        {
            var hashCode = new HashCode();
            hashCode.Add(obj.Residing, StringComparer.OrdinalIgnoreCase);
            hashCode.Add(obj.Visiting, StringComparer.OrdinalIgnoreCase);
            hashCode.Add(obj.Centre, StringComparer.OrdinalIgnoreCase);
            hashCode.Add(obj.Category, StringComparer.OrdinalIgnoreCase);
            return hashCode.ToHashCode();
        }
    }
}