public void TestEmptyListOperations() { FVList <int> a = new FVList <int>(); FVList <int> b = new FVList <int>(); a.AddRange(b); a.InsertRange(0, b); a.RemoveRange(0, 0); Assert.That(!a.Remove(0)); Assert.That(a.IsEmpty); Assert.That(a.WithoutFirst(0).IsEmpty); a.Add(1); Assert.That(a.WithoutFirst(1).IsEmpty); b.AddRange(a); ExpectList(b, 1); b.RemoveAt(0); Assert.That(b.IsEmpty); b.InsertRange(0, a); ExpectList(b, 1); b.RemoveRange(0, 1); Assert.That(b.IsEmpty); b.Insert(0, a[0]); ExpectList(b, 1); b.Remove(a.First); Assert.That(b.IsEmpty); AssertThrows <InvalidOperationException>(delegate() { a.PreviousIn(b); }); }
private void TestTransform(int count, int[] expect, int commonTailLength, params XfAction[] actions) { FVList <int> list = new FVList <int>(); for (int i = 0; i < count; i++) { list.Add(i + 1); } int counter = 0; FVList <int> result = list.Transform(delegate(int i, ref int item) { if (i >= 0) { Assert.AreEqual(list[i], item); } item *= 10; return(actions[counter++]); }); Assert.AreEqual(counter, actions.Length); ExpectList(result.ToRVList(), expect); Assert.That(result.WithoutFirst(result.Count - commonTailLength) == list.WithoutFirst(list.Count - commonTailLength)); }
public void TestSelect() { FVList <int> one = new FVList <int>(3); FVList <int> two = one.Clone().Add(2); FVList <int> thr = two.Clone().Add(1); ExpectList(thr, 1, 2, 3); ExpectList(one.Select(delegate(int i) { return(i + 1); }), 4); ExpectList(two.Select(delegate(int i) { return(i + 1); }), 3, 4); ExpectList(thr.Select(delegate(int i) { return(i + 1); }), 2, 3, 4); ExpectList(two.Select(delegate(int i) { return(i == 3 ? 3 : 0); }), 0, 3); ExpectList(thr.Select(delegate(int i) { return(i == 3 ? 3 : 0); }), 0, 0, 3); ExpectList(thr.Select(delegate(int i) { return(i == 1 ? 0 : i); }), 0, 2, 3); Assert.That(one.SmartSelect(delegate(int i) { return(i); }) == one); Assert.That(two.SmartSelect(delegate(int i) { return(i); }) == two); Assert.That(thr.SmartSelect(delegate(int i) { return(i); }) == thr); ExpectList(one.SmartSelect(delegate(int i) { return(i + 1); }), 4); ExpectList(two.SmartSelect(delegate(int i) { return(i + 1); }), 3, 4); ExpectList(thr.SmartSelect(delegate(int i) { return(i + 1); }), 2, 3, 4); ExpectList(two.SmartSelect(delegate(int i) { return(i == 3 ? 3 : 0); }), 0, 3); ExpectList(thr.SmartSelect(delegate(int i) { return(i == 3 ? 3 : 0); }), 0, 0, 3); ExpectList(thr.SmartSelect(delegate(int i) { return(i == 1 ? 0 : i); }), 0, 2, 3); Assert.That(thr.SmartSelect(delegate(int i) { return(i == 1 ? 0 : i); }).WithoutFirst(1) == two); }
public FVList <T> AddRange(FVList <T> list) { if (IsEmpty) { return(this = list); } return(AddRange(list, new FVList <T>())); }
public void TestInsertRemove() { FWList <int> list = new FWList <int>(); for (int i = 0; i <= 12; i++) { list.Insert(i, i); } ExpectList(list, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); for (int i = 1; i <= 6; i++) { list.RemoveAt(i); } ExpectList(list, 0, 2, 4, 6, 8, 10, 12); Assert.AreEqual(0, list.Pop()); list.Insert(5, -2); ExpectList(list, 2, 4, 6, 8, 10, -2, 12); list.Insert(5, -1); ExpectList(list, 2, 4, 6, 8, 10, -1, -2, 12); list.Remove(-1); list.Remove(12); list[list.Count - 1] = 12; ExpectList(list, 2, 4, 6, 8, 10, 12); // Make sure FWList.Clear doesn't disturb FVList FVList <int> v = list.WithoutFirst(4); list.Clear(); ExpectList(list); ExpectList(v, 10, 12); // Some simple InsertRange calls where some immutable items must be // converted to mutable FVList <int> oneTwo = new FVList <int>(1, 2); FVList <int> threeFour = new FVList <int>(3, 4); list = oneTwo.ToFWList(); list.InsertRange(1, threeFour); ExpectList(list, 1, 3, 4, 2); list = threeFour.ToFWList(); list.InsertRange(2, oneTwo); ExpectList(list, 3, 4, 1, 2); // More tests... list.RemoveRange(0, 2); ExpectList(list, 1, 2); list.InsertRange(2, new int[] { 3, 3, 4, 4, 4, 5, 6, 7, 8, 9 }); ExpectList(list, 1, 2, 3, 3, 4, 4, 4, 5, 6, 7, 8, 9); list.RemoveRange(3, 3); ExpectList(list, 1, 2, 3, 4, 5, 6, 7, 8, 9); v = list.ToFVList(); list.RemoveRange(5, 4); ExpectList(list, 1, 2, 3, 4, 5); ExpectList(v, 1, 2, 3, 4, 5, 6, 7, 8, 9); }
/// <summary>Returns whether the two list references are the same. /// Does not compare the contents of the lists.</summary> public override bool Equals(object rhs_) { try { FVList <T> rhs = (FVList <T>)rhs_; return(this == rhs); } catch (InvalidCastException) { return(false); } }
public Enumerator(FVList <T> list, FVList <T> subList) { _outerList = list; int localCount; _nextBlock = VListBlock <T> .FindNextBlock(ref subList, _outerList, out localCount)._block; _localIndex = (ushort)(checked ((ushort)subList._localCount) - 1); _curBlock = subList._block; _localCount = checked ((ushort)localCount); }
public void TestMultithreadedAdds() { object @lock = new object(); FVList <int> basisList = new FVList <int>(); List <Thread> threads = new List <Thread>(); foreach (int seed_ in new int[] { 0, 10000, 20000 }) { int seed = seed_; // capture loop variable Thread t = new Thread(delegate() { FVList <int> list; int count; for (int i = 0; i < 10000; i++) { lock (@lock) { list = basisList; count = list.Count; } list.Add(seed + i); Assert.AreEqual(count + 1, list.Count); Assert.AreEqual(seed + i, list.First); if (seed == 0) { list.Pop(); } lock (@lock) { basisList = list; } } }); t.Start(); threads.Add(t); } bool done; do { done = true; for (int i = 0; i < threads.Count; i++) { if (threads[i].IsAlive) { done = false; } } } while (!done); Assert.That(true); // breakpoint }
public bool MoveNext() { if (_tail._localCount > 0) { _current = _tail.First; _tail = _tail.Tail; return(true); } else { return(false); } }
public void TestMutabilification() { // Make a single block mutable FVList <int> v = new FVList <int>(0, 1); FWList <int> w = v.ToFWList(); ExpectList(w, 0, 1); w[0] = 2; ExpectList(w, 2, 1); ExpectList(v, 0, 1); // Make another block, make the front block mutable, then the block-of-2 v.Push(-1); w = v.ToFWList(); w[0] = 3; ExpectList(w, 3, 0, 1); Assert.That(w.WithoutFirst(1) == v.WithoutFirst(1)); w[1] = 2; ExpectList(w, 3, 2, 1); Assert.That(w.WithoutFirst(1) != v.WithoutFirst(1)); // Now for a more complicated case: create a long immutable chain by // using a nasty access pattern, add a mutable block in front, then // make some of the immutable blocks mutable. This will cause several // immutable blocks to be consolidated into one mutable block, // shortening the chain. v = new FVList <int>(6); v = v.Add(-1).Tail.Add(5).Add(-1).Tail.Add(4).Add(-1).Tail.Add(3); v = v.Add(-1).Tail.Add(2).Add(-1).Tail.Add(1).Add(-1).Tail.Add(0); ExpectList(v, 0, 1, 2, 3, 4, 5, 6); // At this point, every block in the chain has only one item (it's // a linked list!) and the capacity of each block is 2. Assert.AreEqual(7, v.BlockChainLength); w = v.ToFWList(); w.AddRange(new int[] { 5, 4, 3, 2, 1 }); Assert.AreEqual(w.Count, 12); ExpectList(w, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6); // Indices: 0 1 2 3 4 5 6 7 8 9 10 11 // Blocks: block A | B | C| D| E| F| G| H Assert.AreEqual(8, w.BlockChainLength); Assert.AreEqual(4, w.LocalCount); w[8] = -3; ExpectList(w, 5, 4, 3, 2, 1, 0, 1, 2, -3, 4, 5, 6); // Blocks: block A | block I | F| G| H Assert.AreEqual(5, w.BlockChainLength); }
public override FVList <T> SubList(int localIndex) { if (-localIndex >= PriorCount) { return(new FVList <T>()); // empty } FVList <T> list = new FVList <T>(this, localIndex); while (list._localCount <= 0) { FVList <T> prior = list._block.Prior; list._block = prior._block; list._localCount += prior._localCount; } return(list); }
public void TestWhere() { FVList <int> one = new FVList <int>(3); FVList <int> two = one.Clone().Add(2); FVList <int> thr = two.Clone().Add(1); ExpectList(one.Where(delegate(int i) { return(false); })); ExpectList(two.Where(delegate(int i) { return(false); })); ExpectList(thr.Where(delegate(int i) { return(false); })); Assert.That(one.Where(delegate(int i) { return(true); }) == one); Assert.That(two.Where(delegate(int i) { return(true); }) == two); Assert.That(thr.Where(delegate(int i) { return(true); }) == thr); Assert.That(two.Where(delegate(int i) { return(i == 3); }) == one); Assert.That(thr.Where(delegate(int i) { return(i == 3); }) == one); Assert.That(thr.Where(delegate(int i) { return(i > 1); }) == two); ExpectList(two.Where(delegate(int i) { return(i == 2); }), 2); ExpectList(thr.Where(delegate(int i) { return(i == 2); }), 2); }
public void TestToArray() { FVList <int> list = new FVList <int>(); int[] array = list.ToArray(); Assert.AreEqual(array.Length, 0); array = list.Add(1).ToArray(); ExpectList(array, 1); array = list.Add(2).ToArray(); ExpectList(array, 2, 1); array = list.Add(3).ToArray(); ExpectList(array, 3, 2, 1); array = list.AddRange(new int[] { 8, 7, 6, 5, 4 }).ToArray(); ExpectList(array, 8, 7, 6, 5, 4, 3, 2, 1); }
public void TestInsertRemove() { FVList <int> list = new FVList <int>(9); FVList <int> list2 = new FVList <int>(10, 11); list.Insert(1, 12); list.Insert(1, list2[0]); list.Insert(2, list2[1]); ExpectList(list, 9, 10, 11, 12); for (int i = 0; i < 9; i++) { list.Insert(i, i); } ExpectList(list, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); list2 = list; for (int i = 1; i <= 6; i++) { list2.RemoveAt(i); } ExpectList(list2, 0, 2, 4, 6, 8, 10, 12); ExpectList(list, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); // unchanged Assert.AreEqual(0, list2.Pop()); list2.Insert(5, -2); ExpectList(list2, 2, 4, 6, 8, 10, -2, 12); list2.Insert(5, -1); ExpectList(list2, 2, 4, 6, 8, 10, -1, -2, 12); // Test changing items list = list2; for (int i = 0; i < list.Count; i++) { list[i] = i; } ExpectList(list, 0, 1, 2, 3, 4, 5, 6, 7); ExpectList(list2, 2, 4, 6, 8, 10, -1, -2, 12); list2.Clear(); ExpectList(list2); Assert.AreEqual(5, list[5]); }
/// <summary>Inits an empty block.</summary> /// <param name="localCapacity">Max item count in this block, or zero to /// let the constructor choose the capacity.</param> /// <remarks>If this constructor is called directly, mutable must be true, /// because immutable blocks must have at least one item. /// </remarks> public VListBlockArray(FVList <T> prior, int localCapacity, bool mutable) { if (prior._block == null) { throw new ArgumentNullException("prior"); } _prior = prior; _priorCount = prior.Count; if (localCapacity <= 0) { localCapacity = Math.Min(MAX_BLOCK_LEN, Math.Max(prior._localCount * 2, prior._block.ImmCount)); } _array = new T[localCapacity]; if (mutable) { _immCount |= MutableFlag; } }
public void TestInsertRemoveRange() { FVList <int> oneTwo = new FVList <int>(1, 2); FVList <int> threeFour = new FVList <int>(3, 4); FVList <int> list = oneTwo; FVList <int> list2 = threeFour; ExpectList(list, 1, 2); list.InsertRange(1, threeFour); ExpectList(list, 1, 3, 4, 2); list2.InsertRange(2, oneTwo); ExpectList(list2, 3, 4, 1, 2); list.RemoveRange(1, 2); ExpectList(list, 1, 2); list2.RemoveRange(2, 2); ExpectList(list2, 3, 4); list.RemoveRange(0, 2); ExpectList(list); list2.RemoveRange(1, 1); ExpectList(list2, 3); list = threeFour; list.AddRange(oneTwo); ExpectList(list, 1, 2, 3, 4); list.InsertRange(1, list); ExpectList(list, 1, 1, 2, 3, 4, 2, 3, 4); list.RemoveRange(1, 1); list.RemoveRange(4, 3); ExpectList(list, 1, 2, 3, 4); list.RemoveRange(0, 4); ExpectList(list); list2.InsertRange(0, list); list2.InsertRange(1, list); ExpectList(list2, 3); }
public FVList <T> SmartAdd(T item, ref FVList <T> original) { if (original._block != null && this._block != null) { int thisCount = _localCount; int oldCount = original._localCount; if (original._block != this._block) { thisCount += _block.PriorCount; oldCount += original._block.PriorCount; } if (oldCount > thisCount) { int locali = original._localCount - (oldCount - thisCount); if (EqualityComparer.Equals(item, original._block[locali]) && original._block.SubList(locali) == this) { return(original._block.SubList(locali + 1)); } } original = new FVList <T>(); } return(Add(item)); }
public bool MoveNext() { if (++_localIndex >= _localCount) { _curBlock = _nextBlock; if (_curBlock == null) { return(false); } int localCount; // The FVList constructed here usually violates the invariant // (_localCount == 0) == (_block == null), but FindNextBlock // doesn't mind. It's necessary to avoid the "subList is not // within list" exception in all cases. FVList <T> subList = new FVList <T>(_curBlock, 0); _nextBlock = VListBlock <T> .FindNextBlock( ref subList, _outerList, out localCount)._block; _localCount = checked ((ushort)localCount); _localIndex = 0; } return(true); }
public FVList <T> AddRange(FVList <T> list, FVList <T> excludeSubList) { this = VListBlock <T> .AddRange(_block, _localCount, list, excludeSubList); return(this); }
public Enumerator(FVList <T> list) : this(list, new FVList <T>()) { }
/// <summary>Inits an immutable block with one item.</summary> public VListBlockArray(FVList <T> prior, T firstItem) : this(prior, 0, false) { _array[0] = firstItem; _immCount = 1; }
public FVList <T> PreviousIn(FVList <T> largerList) { return(VListBlock <T> .BackUpOnce(this, largerList)); }
public void RandomTest() { int seed = Environment.TickCount; Random r = new Random(seed); int action, index, iteration = 0, i = -1; FWList <int> wlist = new FWList <int>(); List <int> list = new List <int>(); // Perform a series of random operations on FWList: // - Calling the setter // - RemoveAt // - Add to front // - Insert // - Making part of the list immutable try { for (iteration = 0; iteration < 100; iteration++) { action = r.Next(5); int range = list.Count + (action >= 2 ? 1 : 0); if (range == 0) { iteration--; continue; } index = r.Next(range); switch (action) { case 0: list.RemoveAt(index); wlist.RemoveAt(index); break; case 1: list[index] = iteration; wlist[index] = iteration; break; case 2: list.Insert(0, iteration); wlist.Add(iteration); break; case 3: list.Insert(index, iteration); wlist.Insert(index, iteration); break; case 4: FVList <int> v = wlist.WithoutFirst(index); if (r.Next(2) == 0) { v.Add(index); } break; } Assert.AreEqual(list.Count, wlist.Count); for (i = 0; i < list.Count; i++) { Assert.AreEqual(list[i], wlist[i]); } } } catch (Exception e) { Console.WriteLine("{0} with seed {1} at iteration {2}, i={3}", e.GetType().Name, seed, iteration, i); throw; } }
public FVList <T> AddRange(FVList <T> list) { return(AddRange(list, new FVList <T>())); }
public void SimpleTests() { // Tests simple adds and removes from the front of the list. It // makes part of its tail immutable, but doesn't make it mutable // again. Also, we test operations that don't modify the list. FWList <int> list = new FWList <int>(); Assert.That(list.IsEmpty); // create VListBlockOfTwo list = new FWList <int>(10, 20); ExpectList(list, 10, 20); // Add() list.Clear(); list.Add(1); Assert.That(!list.IsEmpty); list.Add(2); Assert.AreEqual(1, list.BlockChainLength); list.Add(3); Assert.AreEqual(2, list.BlockChainLength); ExpectList(list, 3, 2, 1); FVList <int> snap = list.ToFVList(); ExpectList(snap, 3, 2, 1); // AddRange(), Push(), Pop() list.Push(4); list.AddRange(new int[] { 6, 5 }); ExpectList(list, 6, 5, 4, 3, 2, 1); Assert.AreEqual(list.Pop(), 6); ExpectList(list, 5, 4, 3, 2, 1); list.RemoveRange(0, 2); ExpectList(list, 3, 2, 1); // Double the list list.AddRange(list); ExpectList(list, 3, 2, 1, 3, 2, 1); list.RemoveRange(0, 3); // Fill a third block list.AddRange(new int[] { 9, 8, 7, 6, 5, 4 }); list.AddRange(new int[] { 14, 13, 12, 11, 10 }); ExpectList(list, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); // Remove(), enumerator list.Remove(14); list.Remove(13); list.Remove(12); list.Remove(11); ExpectListByEnumerator(list, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); // IndexOutOfRangeException AssertThrows <IndexOutOfRangeException>(delegate() { int i = list[-1]; }); AssertThrows <IndexOutOfRangeException>(delegate() { int i = list[10]; }); AssertThrows <IndexOutOfRangeException>(delegate() { list.Insert(-1, -1); }); AssertThrows <IndexOutOfRangeException>(delegate() { list.Insert(list.Count + 1, -1); }); AssertThrows <IndexOutOfRangeException>(delegate() { list.RemoveAt(-1); }); AssertThrows <IndexOutOfRangeException>(delegate() { list.RemoveAt(list.Count); }); // Front, Contains, IndexOf Assert.That(list.First == 10); Assert.That(list.Contains(9)); Assert.That(list[list.IndexOf(2)] == 2); Assert.That(list[list.IndexOf(9)] == 9); Assert.That(list[list.IndexOf(7)] == 7); Assert.That(list.IndexOf(-1) == -1); // snap is still the same ExpectList(snap, 3, 2, 1); }
/// <summary>Adds the specified item to the list, or /// original.WithoutFirst(original.Count - Count - 1) /// if doing so is equivalent.</summary> /// <param name="item">Item to add</param> /// <param name="original">An old version of the list</param> /// <returns>Returns this.</returns> /// <remarks> /// This method helps write functional code in which you process an input /// list and produce an output list that may or may not be the same as the /// input list. In case the output list is identical, you would prefer /// to return the original input list rather than wasting memory on a new /// list. SmartAdd() helps you do this. The following method demonstrates /// SmartAdd() by removing all negative numbers from a list: /// <example> /// FVList<int> RemoveNegative(FVList<int> input) /// { /// var output = FVList<int>.Empty; /// // Enumerate tail-to-head /// foreach (int n in (RVList<int>)input) /// if (n >= 0) /// output.SmartAdd(n, input); /// return output; /// } /// </example> /// You could also do the same thing with input.Filter(delegate(int i) { return i; } >= 0) /// </remarks> public FVList <T> SmartAdd(T item, FVList <T> original) { return(SmartAdd(item, ref original)); }
public void SimpleTests() { // In this simple test, I only add and remove items from the front // of a FVList, but forking is also tested. FVList <int> list = new FVList <int>(); Assert.That(list.IsEmpty); // Adding to VListBlockOfTwo list = new FVList <int>(10, 20); ExpectList(list, 10, 20); list = new FVList <int>(); list.Add(1); Assert.That(!list.IsEmpty); list.Add(2); ExpectList(list, 2, 1); // A fork in VListBlockOfTwo. Note that list2 will use two VListBlocks // here but list will only use one. FVList <int> list2 = list.WithoutFirst(1); list2.Add(3); ExpectList(list, 2, 1); ExpectList(list2, 3, 1); // Try doubling list2 list2.AddRange(list2); ExpectList(list2, 3, 1, 3, 1); // list now uses two arrays list.Add(4); ExpectList(list, 4, 2, 1); // Try doubling list using a different overload of AddRange() list.AddRange((IList <int>)list); ExpectList(list, 4, 2, 1, 4, 2, 1); list = list.WithoutFirst(3); ExpectList(list, 4, 2, 1); // Remove(), Pop() Assert.That(list2.Remove(3)); ExpectList(list2, 1, 3, 1); Assert.That(!list2.Remove(0)); Assert.AreEqual(1, list2.Pop()); Assert.That(list2.Remove(3)); ExpectList(list2, 1); Assert.AreEqual(1, list2.Pop()); ExpectList(list2); AssertThrows <Exception>(delegate() { list2.Pop(); }); // Add many, SubList(). This will fill 3 arrays (sizes 8, 4, 2) and use // 1 element of a size-16 array. Oh, and test the enumerator. for (int i = 5; i <= 16; i++) { list.Add(i); } ExpectList(list, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 2, 1); list2 = list.WithoutFirst(6); ExpectListByEnumerator(list2, 10, 9, 8, 7, 6, 5, 4, 2, 1); AssertThrows <IndexOutOfRangeException>(delegate() { int i = list[-1]; }); AssertThrows <IndexOutOfRangeException>(delegate() { int i = list[15]; }); // IndexOf, contains Assert.That(list.Contains(11)); Assert.That(!list2.Contains(11)); Assert.That(list[list.IndexOf(2)] == 2); Assert.That(list[list.IndexOf(1)] == 1); Assert.That(list[list.IndexOf(15)] == 15); Assert.That(list.IndexOf(3) == -1); // PreviousIn(), this[], Front FVList <int> list3 = list2; Assert.AreEqual(11, (list3 = list3.PreviousIn(list))[0]); Assert.AreEqual(12, (list3 = list3.PreviousIn(list))[0]); Assert.AreEqual(13, (list3 = list3.PreviousIn(list))[0]); Assert.AreEqual(14, (list3 = list3.PreviousIn(list)).First); Assert.AreEqual(15, (list3 = list3.PreviousIn(list)).First); Assert.AreEqual(16, (list3 = list3.PreviousIn(list)).First); AssertThrows <Exception>(delegate() { list3.PreviousIn(list); }); // Tail Assert.AreEqual(10, (list3 = list3.WithoutFirst(6))[0]); Assert.AreEqual(9, (list3 = list3.Tail)[0]); Assert.AreEqual(8, (list3 = list3.Tail)[0]); Assert.AreEqual(7, (list3 = list3.Tail).First); Assert.AreEqual(6, (list3 = list3.Tail).First); Assert.AreEqual(5, (list3 = list3.Tail).First); Assert.AreEqual(4, (list3 = list3.Tail)[0]); Assert.AreEqual(2, (list3 = list3.Tail)[0]); Assert.AreEqual(1, (list3 = list3.Tail)[0]); Assert.That((list3 = list3.Tail).IsEmpty); // list2 is still the same ExpectList(list2, 10, 9, 8, 7, 6, 5, 4, 2, 1); // ==, !=, Equals(), AddRange(a, b) Assert.That(!list2.Equals("hello")); list3 = list2; Assert.That(list3.Equals(list2)); Assert.That(list3 == list2); // This AddRange forks the list. List2 end up with block sizes 8 (3 // used), 8 (3 used), 4, 2. list2.AddRange(list2, list2.WithoutFirst(3)); ExpectList(list2, 10, 9, 8, 10, 9, 8, 7, 6, 5, 4, 2, 1); Assert.That(list3 != list2); // List3 is a sublist of list, but list2 no longer is Assert.That(list3.PreviousIn(list).First == 11); AssertThrows <InvalidOperationException>(delegate() { list2.PreviousIn(list); }); list2 = list2.WithoutFirst(3); Assert.That(list3 == list2); }
public Enumerator(RVList <T> list) { _tail = (FVList <T>)list; _current = default(T); }