Skip to content

Instantly share code, notes, and snippets.

@in-async
Created January 20, 2024 08:56
Show Gist options
  • Save in-async/38d9ec2edcb6332a0bd545a83859b9e1 to your computer and use it in GitHub Desktop.
Save in-async/38d9ec2edcb6332a0bd545a83859b9e1 to your computer and use it in GitHub Desktop.
クエリ パラメータ順に依存しない `Uri` 比較子 (と、クエリ値がカンマ区切りのコレクションの場合に、そちらも順序非依存とする為のアイテム比較子) の仮組み
internal sealed class UriComparer : IEqualityComparer<Uri> {
private readonly IEqualityComparer<KeyValuePair<string, StringValues>> _queryComparer;
public UriComparer(IEqualityComparer<KeyValuePair<string, StringValues>>? queryComparer = null) {
_queryComparer = queryComparer ?? EqualityComparer<KeyValuePair<string, StringValues>>.Default;
}
public bool Equals(Uri? x, Uri? y) {
if (x == y) { return true; }
if (x is null || y is null) { return false; }
if (Uri.Compare(x, y, UriComponents.HttpRequestUrl ^ UriComponents.Query, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase) != 0) { return false; }
return x.GetQueryStrings().SequenceEqual(y.GetQueryStrings(), _queryComparer);
}
public int GetHashCode([DisallowNull] Uri obj) {
HashCode hash = new();
hash.Add(obj.GetComponents(UriComponents.HttpRequestUrl ^ UriComponents.Query, UriFormat.UriEscaped));
foreach (KeyValuePair<string, StringValues> item in obj.GetQueryStrings()) {
hash.Add(item, _queryComparer);
}
return hash.ToHashCode();
}
}
internal sealed class CommaQueryComparer : IEqualityComparer<KeyValuePair<string, StringValues>> {
public bool Equals(KeyValuePair<string, StringValues> x, KeyValuePair<string, StringValues> y) {
if (x.Equals(y)) { return true; }
if (x.Key != y.Key) { return false; }
if (x.Value.Count != y.Value.Count) { return false; }
for (int i = 0; i < x.Value.Count; i++) {
IEnumerable<string> xSeq = x.Value[i]?.Split(',').Order() ?? Enumerable.Empty<string>();
IEnumerable<string> ySeq = y.Value[i]?.Split(',').Order() ?? Enumerable.Empty<string>();
if (!xSeq.SequenceEqual(ySeq)) { return false; }
}
return true;
}
public int GetHashCode([DisallowNull] KeyValuePair<string, StringValues> obj) {
HashCode hash = new();
hash.Add(obj.Key);
foreach (string? item in obj.Value) {
hash.Add(item?.Split(',').Order());
}
return hash.ToHashCode();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment