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

[Proposal] For String/NullableString allow specifying StringComparer for use in source generation #99

Closed
espenrl opened this issue Mar 3, 2023 · 1 comment · Fixed by #117

Comments

@espenrl
Copy link

espenrl commented Mar 3, 2023

String comparison can be

  • CurrentCulture
  • CurrentCultureIgnoreCase
  • InvariantCulture
  • InvariantCultureIgnoreCase
  • Ordinal
  • OrdinalIgnoreCase

Please see https://learn.microsoft.com/en-us/dotnet/api/system.stringcomparison for more details.

It would be a great enhancement to StronglyTypedId if one could specify which one to use.


This is the source generated for a string (for the latest version of StronglyTypedId).

readonly partial struct OrderId : System.IComparable<OrderId>, System.IEquatable<OrderId>
{
    public string Value { get; }

    public OrderId(string value)
    {
        Value = value ?? throw new System.ArgumentNullException(nameof(value));
    }

    public static readonly OrderId Empty = new OrderId(string.Empty);

    public bool Equals(OrderId other)
    {
        return (Value, other.Value) switch
        {
            (null, null) => true,
            (null, _) => false,
            (_, null) => false,
            (_, _) => Value.Equals(other.Value),
        };
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
            return false;
        return obj is OrderId other && Equals(other);
    }

    public override int GetHashCode() => Value.GetHashCode(StringComparison.OrdinalIgnoreCase);

    public override string ToString() => Value;
    public static bool operator ==(OrderId a, OrderId b) => a.Equals(b);
    public static bool operator !=(OrderId a, OrderId b) => !(a == b);
    public int CompareTo(OrderId other)
    {
        return (Value, other.Value) switch
        {
            (null, null) => 0,
            (null, _) => -1,
            (_, null) => 1,
            (_, _) => Value.CompareTo(other.Value),
        };
    }
}

And this is how it could look like with StringComparison.OrdinalIgnoreCase. Note the changes in Equals(OrderId other), CompareTo(OrderId other) and GetHashCode(). The null checks are not needed when using string.Equals and string.Compare.

readonly partial struct OrderId : System.IComparable<OrderId>, System.IEquatable<OrderId>
{
    public string Value { get; }

    public OrderId(string value)
    {
        Value = value ?? throw new System.ArgumentNullException(nameof(value));
    }

    public static readonly OrderId Empty = new OrderId(string.Empty);

    public bool Equals(OrderId other)
    {
        return string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase);
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
            return false;
        return obj is OrderId other && Equals(other);
    }

    public override int GetHashCode() => Value.GetHashCode();

    public override string ToString() => Value;
    public static bool operator ==(OrderId a, OrderId b) => a.Equals(b);
    public static bool operator !=(OrderId a, OrderId b) => !(a == b);
    public int CompareTo(OrderId other)
    {
        return string.Compare(Value, other.Value, StringComparison.OrdinalIgnoreCase);
    }
}

The StronglyTypedIdAttribute would need a new option to specify the StringComparison and possibly also StronglyTypedIdDefaultsAttribute.

@andrewlock
Copy link
Owner

This is a great point. In #117 I've changed to use StringComparison.Ordinal instead of the current culture. Additionally, that PR allows complete customisation of the IDs, so you can create a custom template for this behaviour 🙂

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

Successfully merging a pull request may close this issue.

2 participants