Skip to content

Instantly share code, notes, and snippets.

@in-async
Last active July 23, 2021 04:21
Show Gist options
  • Save in-async/5175ca7ddce7d25f7cf2236eb72ee411 to your computer and use it in GitHub Desktop.
Save in-async/5175ca7ddce7d25f7cf2236eb72ee411 to your computer and use it in GitHub Desktop.
シーケンスの比較を行う `IComparer<T>` 実装。
#nullable enable
using System;
using System.Collections.Generic;
namespace Commons {
/// <summary>
/// シーケンスの比較を行う <see cref="IComparer{T}"/> 実装。
/// </summary>
/// <typeparam name="T">比較対象となるシーケンスの要素型。</typeparam>
public class EnumerableComparer<T> : IComparer<IEnumerable<T>?> {
private readonly IComparer<T> _elementComparer;
/// <summary>
/// Initializes a new instance of the <see cref="EnumerableComparer{T}"/> class.
/// </summary>
/// <param name="elementComparer">要素の比較子。</param>
/// <exception cref="ArgumentNullException"><paramref name="elementComparer"/> is <c>null</c>.</exception>
public EnumerableComparer(IComparer<T> elementComparer) {
_elementComparer = elementComparer ?? throw new ArgumentNullException(nameof(elementComparer));
}
/// <inheritdoc />
public int Compare(IEnumerable<T>? x, IEnumerable<T>? y) {
if (x == y) { return 0; }
if (x is null) { return -1; }
if (y is null) { return 1; }
using IEnumerator<T> xIter = x.GetEnumerator();
using IEnumerator<T> yIter = y.GetEnumerator();
while (true) {
switch ((xIter.MoveNext(), yIter.MoveNext())) {
case (false, false):
return 0;
case (false, true):
return -1;
case (true, false):
return 1;
}
switch (_elementComparer.Compare(xIter.Current, yIter.Current)) {
case < 0:
return -1;
case > 0:
return 1;
}
}
}
}
}
#nullable restore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment