0
在下面的struct中,我使用函数来跟随策略模式。为什么struct在使用函数时不会改变?
这是一个简单的范围枚举器。 如果通过否定长度,则会反向枚举。
它如何不按预期工作。当_move
呼叫返回时,Position
保持不变。
我想我知道原因,因为结构被复制到某个地方。但我似乎无法找到复制的地方。
(使用类,而不是struct没有回答我要找的。)
internal struct RangeEnumerator<T> : IEnumerator<T>
{
private readonly Func<bool> _move;
private readonly IReadOnlyList<T> _source;
private readonly int _start;
private readonly int _end;
// position of enumerator. not actual index. negative if reversed
public int Position { get; private set; }
public RangeEnumerator(IReadOnlyList<T> source, int start, int length)
{
start = Math.Min(Math.Max(start, 0), source.Count);
_source = source;
_start = start;
_end = Math.Min(Math.Max(length + start, 0), source.Count);
Position = -Math.Sign(length);
_move = null;
_move = length >= 0 ? (Func<bool>) this.MoveNextImpl : this.MovePrevImpl;
}
public bool MoveNext() => _move();
public void Reset() => Position = -1;
public T Current => _source[Position + _start];
object IEnumerator.Current => Current;
private bool MoveNextImpl() => ++Position + _start < _end;
private bool MovePrevImpl() => --Position + _start >= _end;
void IDisposable.Dispose()
{
}
}
测试:进行快速测试,使用下面的代码和调试。
public static class Program
{
public static void Main(string[] args)
{
var list = new List<int> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
var enumerator = new RangeEnumerator<int>(list, 3, 5); // 3 to 8 exclusive
foreach (var x in enumerator.AsEnumerable(0))
{
Console.WriteLine(x);
}
}
}
internal static class EnumeratorExtensions
{
public static StructEnumerable<TEnumerator, T> AsEnumerable<TEnumerator, T>(this TEnumerator enumerator, T _) where TEnumerator : struct, IEnumerator<T>
{
// struct copy doesn't matter since we didn't start enumerating yet.
return new StructEnumerable<TEnumerator, T>(enumerator);
}
}
// Enumerable to be used by foreach.
internal struct StructEnumerable<TEnumerator, T> where TEnumerator : struct, IEnumerator<T>
{
private TEnumerator _enumerator;
public StructEnumerable(TEnumerator enumerator)
{
// struct copy doesn't matter since we didn't start enumerating yet.
_enumerator = enumerator;
}
public TEnumerator GetEnumerator()
{
// struct copy doesn't matter since we didn't start enumerating yet.
return _enumerator;
}
}