Understanding Enumerator in List<T> - c#

The source code of Enumerator is:
public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator {
private List<T> list;
private int index;
private int version;
private T current;
...
public bool MoveNext() {
List<T> localList = list; <--------------Q1
if (version == localList._version && ((uint)index < (uint)localList._size)) {
current = localList._items[index];
index++;
return true;
}
return MoveNextRare();
}
private bool MoveNextRare() {
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = list._size + 1; <-----------------Q2
current = default(T);
return false;
}
void System.Collections.IEnumerator.Reset() {
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = 0;
current = default(T);
}
...
}
I have some questions on this iterator pattern:
Q1-Why MoveNext method need to define a localList, can't it just use the private field list directly since List<T> is already a reference type, why need to create an alias for it?
Q2- MoveNextRare method will invoke when the index is out of range of the last element in the list, so what's the point to increment it, why not just leave it untouched, because when Reset() calls, index will be set to 0 anyway?

For the first question I don't have any answer, maybe it just an relic from some previous implementation, maybe it somehow improves performance (though I would wonder how and why, so my bet is on the first guess). Also in the Core implementation list field is marked as readonly.
As for the second one - it has nothing to do with Reset, but with System.Collections.IEnumerator.Current implementation:
Object System.Collections.IEnumerator.Current {
get {
if( index == 0 || index == list._size + 1) { // check second comparasion
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
}
return Current;
}

Related

Foreach calls MoveNext in Enumerator first, Current second

My issue is basically in order of the functions/property called. I have a custom linked list, circular one. So I made a custom enumenator and all. The issue is, the foreach cycle actually calls the MoveNext() method of enumerator first, therefore moving from the actual first Node of the cycle to the second node, which is kind of bad if you want to have your items in actual order.
Question is, am I doing something wrong, and if not, how to compensate for this?
Code of Enumerator is simple as can be. This, basically:
class EnumeratorLinkedList : IEnumerator<Node>
{
private Node current;
private Node first;
private bool didWeMove;
public EnumeratorSpojovySeznam(Node current)
{
this.current = current;
this.first = current;
didWeMove = false;
}
public Node Current => current;
object System.Collections.IEnumerator.Current => Current;
public bool MoveNext()
{
if ((didWeMove == true && current == first)) return false;
current = current.Next;
didWeMove = true;
return true;
}
public void Dispose()
{
}
public void Reset()
{
throw new NotImplementedException();
}
}
Do you consider using C# iterators to implement enumerator for your circular LinkedList? If you do, it is very simple. Iterators provide convenient and easy way to implement enumerators.
Here is how enumerator can be implemented for your circular LinkedList:
class LinkedList : IEnumerable<Node>
{
private Node first;
public IEnumerator<Node> GetEnumerator()
{
// Check if LinkedList is empty.
// If it is empty we immediately break enumeration.
if (first == null)
yield break;
// Here goes logic for enumerating circular LinkedList.
Node current = first;
do
{
yield return current;
current = current.Next;
} while (current != first);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
As you can see an implementation using iterator is more straightforward and intuitive.
Here is complete sample that demonstrates usage of iterators.

Clear in LinkedList for O(N). Why?

The built-in implementation of the LinkedList is a doubly-linked circular list.
I see the following implementation of the Clear method:
public void Clear() {
LinkedListNode<T> current = head;
while (current != null ) {
LinkedListNode<T> temp = current;
current = current.Next;
temp.Invalidate();
}
head = null;
count = 0;
version++;
}
So, this clearing method apparently works for O(N).
public sealed class LinkedListNode<T> {
internal LinkedList<T> list;
internal LinkedListNode<T> next;
internal LinkedListNode<T> prev;
internal T item;
public LinkedListNode( T value) {
this.item = value;
}
internal LinkedListNode(LinkedList<T> list, T value) {
this.list = list;
this.item = value;
}
public LinkedList<T> List {
get { return list;}
}
public LinkedListNode<T> Next {
get { return next == null || next == list.head? null: next;}
}
public LinkedListNode<T> Previous {
get { return prev == null || this == list.head? null: prev;}
}
public T Value {
get { return item;}
set { item = value;}
}
internal void Invalidate() {
list = null;
next = null;
prev = null;
}
}
I wonder why can't we just assign null to head instead of nulling all the references? As far as I can see, assigning null to the head will result in breaking the circle and all the nodes will be collected by GC pretty soon. Or am I missing something?
This is done so that once the linked list is cleared, anything holding references to its old nodes will throw errors if it tries to navigate the list.
If the old links weren't set to null, the old linked list would remain accessible if anything had a reference to any of its nodes, which would (a) hide the problem because the code would continue to apparently work and (b) keep alive the node objects in memory.

Alternative for the Stack

I am working in .Net environment using C#. I need some alternative for the Stack data structure. Some kind of bound stack. The quantity of elements in the collection shouldn't exceed some fixed specified number. And, if that number achieved and new element is pushed, than most older element must be deleted. I need this for storing commands for Undo/Redo strategies.
A circular buffer should do the job; easy enough to wrap a list or array, but nothing built in AFAIK.
Johnny Coder has an implementation here: http://johnnycoder.com/blog/2008/01/07/undo-functionality-with-a-limited-stack/
This is an implementation of a stack with a constrained capacity.
After reaching the given capacity, bottom items of the stack beyond the capacity are discarded. It is possible to iterate through the contained objects and set the index to a specifc position (like a rewind) for discarding multiple entries at once when pushing a new item to the stack.
This is an own implementation with some goodies that prevents you from handling more then one list if you need to go back in the history and forward again (is builtin).
public class DiscardingStack<TObject> : IEnumerable<TObject>
{
private readonly int capacity;
private readonly List<TObject> items;
private int index = -1;
public DiscardingStack(int capacity)
{
this.capacity = capacity;
items = new List<TObject>(capacity);
}
public DiscardingStack(int capacity, IEnumerable<TObject> collection)
: this(capacity)
{
foreach (var o in collection)
{
Push(o);
}
}
public DiscardingStack(ICollection<TObject> collection)
: this(collection.Count, collection)
{
}
public void Clear()
{
if (items.Count >= 0)
{
items.Clear();
index = items.Count - 1;
}
}
public int Index
{
get { return index; }
set
{
if (index >= 0 && index < items.Count)
{
index = value;
}
else throw new InvalidOperationException();
}
}
public int Count
{
get { return items.Count; }
}
public TObject Current
{
get { return items[index]; }
set { index = items.IndexOf(value); }
}
public int Capacity
{
get { return capacity; }
}
public TObject Pop()
{
if (items.Count <= 0)
throw new InvalidOperationException();
var i = items.Count - 1;
var removed = items[i];
items.RemoveAt(i);
if (index > i)
index = i;
return removed;
}
public void Push(TObject item)
{
if (index == capacity - 1)
{
items.RemoveAt(0);
index--;
}
else if (index < items.Count - 1)
{
var removeAt = index + 1;
var removeCount = items.Count - removeAt;
items.RemoveRange(removeAt, removeCount);
}
items.Add(item);
index = items.Count - 1;
}
public TObject Peek()
{
return items[items.Count-1];
}
public TObject this[int i]
{
get { return items[i]; }
}
public IEnumerator<TObject> GetEnumerator()
{
return items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Anyway, building a stack that discards elements when the maximum capacity is reached should be implemented using a LinkedList (as suggested above) if your list is huge (avoids copying). So the LinkedList idea might be better in such a case instead of wrapping a List if the buffer maximum is a high value.
I would also recommend to pack the Push(), Pop() etc. into an interface (e.g. IStack). Sadly, there is no IStack interface predefined in .Net (afaik).
.Net is rather deficient in type of collections. You'll find a collection library here. Use CircularQueue.
There's no builtin Class for this in Framework. (we dont expect to delete data automatically). But you can very well Extend the Stack class and Override Push/Pop and other Methods to suit your needs.

How to use DataPager with Database Paged

I am using ListView/DataPager.
For performance reasons I page my results at database, using ROW_NUMBER(SQl2005).
At my C# code just comes one page at time. How can I say to DataPager that I have more rows that really are at my List?
I created a class that gerenate fake default(T) objects. Worked fine:
public class PagedList<T> : IEnumerable<T>, ICollection
{
private IEnumerable<T> ActualPage { get; set; }
private int Total { get; set; }
private int StartIndex { get; set; }
public PagedList(int total, int startIndex, IEnumerable<T> actualPage)
{
ActualPage = actualPage;
Total = total;
StartIndex = startIndex;
}
public IEnumerator<T> GetEnumerator()
{
bool passouPagina = false;
for (int i = 0; i < Total; i++)
{
if (i < StartIndex || passouPagina)
{
yield return default(T);
}
else
{
passouPagina = true;
foreach (T itempagina in ActualPage)
{
i++;
yield return itempagina;
}
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#region Implementation of ICollection
void ICollection.CopyTo(Array array, int index)
{
throw new NotSupportedException();
}
public int Count
{
get { return Total; }
}
object ICollection.SyncRoot
{
get { throw new NotSupportedException(); }
}
bool ICollection.IsSynchronized
{
get { throw new NotSupportedException(); }
}
#endregion
}
Usage example:
int totalRows = DB.GetTotalPeople();
int rowIndex = (currentPage-1)*pageSize;
List<Person> peoplePage = DB.GetPeopleAtPage(currentPage);
listview.DataSource = new PagedList(totalRows, rowIndex, peoplePage)
listView.DataBind();
Apparently I can't comment on the above solution, that was provided by Fujiy, however I discovered the following bug:
Inside GetEnumerator() the incrementation in the else branch will always cause the collection to skip one default element, unless you're on the last page of the PagedList.
As an example, if you would create a paged list of 5 elements, with startindex 3 and 1 element per page. This could would enter the else branch for element 2. It would increment i to 3 and then go back into the for-header where it would increment to 4, without creating a default element for i == 3.
i == 1 -> default
i == 2 -> default
i == 3 -> Actual element
i == 4 -> Skipped
i == 5 -> default
A simple solution would be to either use 3 for-loops (one for defaults before the ActualPage, one for the ActualPage and one for elements after the ActualPage). Or to add a i-- after the For-loop inside the Else-branch.

Is there a SortedList<T> class in .NET? (not SortedList<K,V>)

I need to sort some objects according to their contents (in fact according to one of their properties, which is NOT the key and may be duplicated between different objects).
.NET provides two classes (SortedDictionary and SortedList), and both are implemented using a binary tree. The only differences between them are
SortedList uses less memory than SortedDictionary.
SortedDictionary has faster insertion and removal operations for unsorted data, O(log n) as opposed to O(n) for SortedList.
If the list is populated all at once from sorted data, SortedList is faster than SortedDictionary.
I could achieve what I want using a List, and then using its Sort() method with a custom implementation of IComparer, but it would not be time-efficient as I would sort the whole List each time I want to insert a new object, whereas a good SortedList would just insert the item at the right position.
What I need is a SortedList class with a RefreshPosition(int index) to move only the changed (or inserted) object rather than resorting the whole list each time an object inside changes.
Am I missing something obvious ?
Maybe I'm slow, but isn't this the easiest implementation ever?
class SortedList<T> : List<T>
{
public new void Add(T item)
{
Insert(~BinarySearch(item), item);
}
}
http://msdn.microsoft.com/en-us/library/w4e7fxsh.aspx
Unfortunately, Add wasn't overrideable so I had to new it which isn't so nice when you have List<T> list = new SortedList<T>; which I actually needed to do.... so I went ahead and rebuilt the whole thing...
class SortedList<T> : IList<T>
{
private List<T> list = new List<T>();
public int IndexOf(T item)
{
var index = list.BinarySearch(item);
return index < 0 ? -1 : index;
}
public void Insert(int index, T item)
{
throw new NotImplementedException("Cannot insert at index; must preserve order.");
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public T this[int index]
{
get
{
return list[index];
}
set
{
list.RemoveAt(index);
this.Add(value);
}
}
public void Add(T item)
{
list.Insert(~list.BinarySearch(item), item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(T item)
{
return list.BinarySearch(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
list.RemoveAt(index);
return true;
}
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}
}
Or perhaps something like this is a more appropriate Remove function...
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
while (((IComparable)item).CompareTo((IComparable)list[index]) == 0)
{
if (item == list[index])
{
list.RemoveAt(index);
return true;
}
index++;
}
return false;
}
Assuming items can compare equal but not be equal...
I eventually decided to write it :
class RealSortedList<T> : List<T>
{
public IComparer<T> comparer;
public int SortItem(int index)
{
T item = this[index];
this.RemoveAt(index);
int goodposition=FindLocation(this[index], 0, this.Count);
this.Insert(goodposition, item);
return goodposition;
}
public int FindLocation(T item, int begin, int end)
{
if (begin==end)
return begin;
int middle = begin + end / 2;
int comparisonvalue = comparer.Compare(item, this[middle]);
if (comparisonvalue < 0)
return FindLocation(item,begin, middle);
else if (comparisonvalue > 0)
return FindLocation(item,middle, end);
else
return middle;
}
}
Don't forget that inserting an item into a list backed by an array can be an expensive operation - inserting a bunch of items and then sorting may well be quicker unless you really need to sort after every single operation.
Alternatively, you could always wrap a list and make your add operation find the right place and insert it there.
I've solved this problem in the past by writing an extension method that does a binary search on a IList, and another that does an insert. You can look up the correct implementation in the CLR source because there's a built-in version that works only on arrays, and then just tweak it to be an extension on IList.
One of those "should be in the BCL already" things.
What I need is a SortedList class with
a RefreshPosition(int index) to move
only the changed (or inserted) object
rather than resorting the whole list
each time an object inside changes.
Why would you update using an index when such updates invalidate the index? Really, I would think that updating by object reference would be more convenient. You can do this with the SortedList - just remember that your Key type is the same as the return type of the function that extracts the comparable data form the object.
class UpdateableSortedList<K,V> {
private SortedList<K,V> list = new SortedList<K,V>();
public delegate K ExtractKeyFunc(V v);
private ExtractKeyFunc func;
public UpdateableSortedList(ExtractKeyFunc f) { func = f; }
public void Add(V v) {
list[func(v)] = v;
}
public void Update(V v) {
int i = list.IndexOfValue(v);
if (i >= 0) {
list.RemoveAt(i);
}
list[func(v)] = v;
}
public IEnumerable<T> Values { get { return list.Values; } }
}
Something like that I guess.

Categories

Resources