Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing implementation of IComparable #29

Open
Hanskrogh opened this issue Nov 26, 2024 · 2 comments
Open

Missing implementation of IComparable #29

Hanskrogh opened this issue Nov 26, 2024 · 2 comments

Comments

@Hanskrogh
Copy link

is this something that could be added?

@firenero
Copy link
Owner

@Hanskrogh I'm not sure it makes sense semantically. How do you define that one TypeID is smaller or bigger than another? Theoretically, I could compare timestamps but there are edge cases that make it not that easy to define:

  • What to do if these timestamps are equal? I could compare bytes of UUIDv7 but they generated randomly and it makes comparison ambiguous.
  • What to do with prefixes? It doesn't make sense to compare TypeIDs with different prefixes but IComparable forces to provide this contract.

@Hanskrogh
Copy link
Author

/// https://github.com/mareek/UUIDNext/blob/6d7ff225d3c7cfde3d44d05f630336ce2449be17/Src/UUIDNext/Tools/GuidComparer.cs#L6
/// <summary>
/// Compares two Guids
/// </summary>
public class GuidComparer : IComparer<Guid>
{
    /// <summary>
    /// Compares two Guids and returns an indication of their relative sort order.
    /// </summary>
    public int Compare(Guid x, Guid y)
    {
        Span<byte> xBytes = stackalloc byte[16];
        x.TryWriteBytes(xBytes, bigEndian: true, out _);

        Span<byte> yBytes = stackalloc byte[16];
        y.TryWriteBytes(yBytes, bigEndian: true, out _);

        for (int i = 0; i < 16; i++)
        {
            int compareResult = xBytes[i].CompareTo(yBytes[i]);
            if (compareResult != 0)
            {
                return compareResult;
            }
        }

        return 0;
    }
}

That’s a fair point regarding the ambiguity when comparing TypeIDs with different prefixes. It’s true that semantically comparing them might not make sense in many cases. However, the solution I’ve provided focuses purely on the GUID portion of the TypeID for comparison, leaving it up to the individual programmer to decide whether comparing TypeIDs with different prefixes is meaningful for their use case.

Regarding UUIDv7, its entire purpose is to ensure comparability based on timestamps, and this implementation adheres to that principle by performing a byte-level comparison of the GUID in big-endian order. This approach preserves the natural ordering of UUIDv7, which is inherently timestamp-based.

If two TypeIDs have different prefixes and you still want to compare them, this implementation will default to the underlying GUID order. While this might not always be semantically meaningful, it provides a consistent fallback behavior for scenarios where such comparisons are unavoidable.

Ultimately, the responsibility of ensuring prefix alignment or handling edge cases like identical timestamps would remain with the programmer or the broader application logic. This implementation simply offers a deterministic and timestamp-respecting way to compare TypeIDs when the GUID portion is the focus.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants