Why is Reset function setting wrong value? - c#

I'm supposed to write a LIFO (last in first out) class for chars, which can be edited by Pop and Add functions and seen by Peek function or foreach. Class is working on array to be more optimalized, but foreach for some reason's not working. I tried to make function GetEnumerator based on return value of _arr.GetEnumerator() function, but it was not working, because when I printed item, in console was shown TestApp.LIFO, so I made this, but now foreach won't print a single item and by debuging _i value on Reset function is 0. Can someone say why is it happening and suggest solution?
using System;
using System.Collections;
using System.Collections.Generic;
namespace TestApp {
internal class LIFO : IEnumerator, IEnumerable {
public LIFO(int size) {
_arr = new char[size];
_index = 0;
}
public LIFO(char[] arr) {
_arr = arr.Clone() as char[];
_index = 0;
}
public char Peek() => _index == 0 ? '\0' : _arr[_index - 1];
public bool Add(char c) {
if (_index == _arr.Length)
return false;
try {
_arr[_index] = c;
} catch (Exception) {
return false;
}
++_index;
return true;
}
public void Pop() {
if (_index == 0)
return;
_arr[--_index] = '\0';
}
private int _i;
public IEnumerator GetEnumerator() => this;
public bool MoveNext() => --_i > -1;
public void Reset() => _i = _index - 1;
public object Current => _arr[_i];
private int _index;
private readonly char[] _arr;
}
}
In Program.cs:
using System;
namespace TestApp {
internal static class Program {
private static void Main() {
LIFO l = new(17);
l.Add('k');
l.Add('h');
l.Add('c');
foreach (var item in l)
Console.WriteLine(l);
}
}
}

The issue is that Reset is not called. It is no longer needed but the interface is not changed due to backwards compatibility. Since new iterators implemented using yield return is actually required to throw an exception if Reset is called, no code is expected to call this method anymore.
As such, your iterator index variable, _i, is never initialized and stays at 0. The first call to MoveNext steps it below 0 and then returns false, ending the foreach loop before it even started.
You should always decouple the iterators from your actual collection as it should be safe to enumerate the same collection twice in a nested manner, storing the index variable as an instance variable in your collection prevents this.
You can, however, simplify the enumerator implementation vastly by using yield return like this:
public class LIFO : IEnumerable
{
...
public IEnumerator GetEnumerator()
{
for (int i = _index - 1; i >= 0; i--)
yield return _arr[i];
}
}
You can then remove the _i variable, the MoveNext and Reset methods, as well as the Current property.
If you first want to make your existing code working, with the above note I made about nesting enumerators, you can change your GetEnumerator and Reset methods as follows:
public IEnumerator GetEnumerator()
{
Reset();
return this;
}
public void Reset() => _i = _index;
Note that you have to reset the _i variable to one step past the last (first) value as you're decrementing it inside MoveNext. If you don't, you'll ignore the last item added to the LIFO stack.

Your index counter variable using get values in _arr array (it is _i) and index varible that doing increase and decrease operations on it (it is _index) are different. Because of that your for loop never iterate your collection. I fix the code with some addition here. I hope it's helpful.
LIFO.cs
using System;
using System.Collections;
using System.Collections.Generic;
namespace TestApp
{
internal class LIFO : IEnumerator, IEnumerable
{
public LIFO(int size)
{
_arr = new char[size];
_index = 0;
}
public LIFO(char[] arr)
{
_arr = arr.Clone() as char[];
_index = 0;
}
public int Count() => _index;
public char Peek() => _index == 0 ? '\0' : _arr[_index - 1];
public bool Add(char c)
{
if (_index == _arr.Length)
return false;
try
{
_arr[_index] = c;
}
catch (Exception)
{
return false;
}
++_index;
_i = _index;
return true;
}
public void Pop()
{
if (_index == 0)
return;
_arr[--_index] = '\0';
_i = _index;
}
public IEnumerator GetEnumerator() => (IEnumerator)this;
public bool MoveNext() => --_index > -1;
public void Reset() => _index = _i;
public object Current
{
get => _arr[_index];
}
private int _index;
private int _i;
private readonly char[] _arr;
}
}
Program.cs
using System;
namespace TestApp
{
internal static class Program
{
private static void Main()
{
LIFO l = new LIFO(17);
l.Add('k');
l.Add('h');
l.Add('c');
Console.WriteLine("Count: " + l.Count());
foreach (var i in l)
Console.WriteLine(i);
l.Reset();
foreach (var i in l)
Console.WriteLine(i);
}
}
}

Related

Passing references (And Unity's WWW.progress) to Coroutines/IEnumerators

I've made a coroutine within C# using Unity 5 and I'd like to pass a reference to it. It didn't seem to work so I made a test script to try to isolate the following error.
error CS1623: Iterators cannot have ref or out parameters
Here's the test script:
using UnityEngine;
using System.Collections;
public class TEMP : MonoBehaviour {
// Use this for initialization
void Start () {
float var = 3.141f;
StartCoroutine ( test (ref var) );
}
IEnumerator test (ref float value) {
for (int i = 1; i <= 10; i++) {
Debug.Log (value);
yield return null;
}
}
}
In addition, on my actual script, I'm using Unity's WWW class to download something, and I also get this error when I pass www.progress as a reference:
A property or indexer 'UnityEngine.WWW.progress' may not be passed as 'ref' or 'out' parameter
Remove the ref from the function arguments.
// Use this for initialization
void Start () {
float var = 3.141f;
StartCoroutine ( test (var) );
}
IEnumerator test (float value) {
for (int i = 1; i <= 10; i++) {
Debug.Log (value);
yield return null;
}
}
Based on your requirement you could do something like below with an out parameter. I'm not exactly sure how you are intending to use these methods but I think you are getting the wrong idea about ref arguments and how they work.
class Program
{
static void Main(string[] args)
{
float var = 3.14f;
StartCoroutine(test(var), out var);
}
static IEnumerator test(float value)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine(value);
yield return value + 1;
}
}
static void StartCoroutine(IEnumerator test, out float update)
{
update = 0;
while (test.MoveNext())
{
update++;
Console.WriteLine("Executing..." + update);
}
}
}
However you are never going to be able to pass a ref or out parameter to the interator.
Consider that
IEnumerator test (float value)
{
for (int i = 1; i <= 10; i++)
{
Debug.Log(value);
yield return null;
}
}
Is syntactic sugar for something like:
private class Iterator : IEnumerable<object>, IEnumerator<object>
{
private int _state;
private int _threadId = Environment.CurrentManagedThreadId;
private object _current;
private float _value;
int i;
public Iterator(float value)
{
_value = value;
}
public object Current‎
{
get { return _current; }
}
object IEnumerator.Current
{
get { return _current; }
}
public IEnumerator<object> GetEnumerator()
{
// If we're on the same thread and its the first call, reuse this object as the enumerator
// otherwise create a fresh one for new call (so we don't have buggy overlaps) or a different
// thread (to avoid a race on that first call).
Iterator iter = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : new Iterator(_value);
iter._state = 1;
return iter;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool MoveNext()
{
switch(_state)
{
case 1:
i = 1;
_state = 2;
goto case 2;
case 2:
if (i <= 10)
{
Debug.Log(_value);
_current = null;
++i;
return true;
}
_state = -1;
break;
}
return false;
}
public void Dispose()
{
}
public void Reset()
{
throw new NotSupportedException();
}
}
private IEnumerator test(float value)
{
return new Iterator(value);
}
Now, consider that your float parameter has become a float field in the implementation. Since you can't have a ref field, you can't have it as syntactic sugar for what looks like a ref parameter.
Hence your approach not only won't work (C# won't do it for you with yield taking away a lot of the coding) but can't work.
You'll need to box the float in some way, whether you are holding onto a object reference to the same float, that as a reference-type can be updated by the iterator, or a typed box like:
private class TypedBox<T> where T : struct
{
public T Value { get; set; }
public TypedBox(T value)
{
Value = value;
}
}
That again allows you to access the value via a reference-type, but without the casting cost.
More often its more useful just to have the value iterated based on any values passed in.

Why is List<T>.Enumerator faster than my implementation?

I've found myself in a position where I have to roll my own dynamic array implementation, due to various large performance benefits (in my case). However, after creating an enumerator for my version, and comparing the efficiency with the one List uses, I'm a bit bewildered; the List one is aproximately 30-40% faster than my version, even though it's much more complex.
Here's the important part of the List enumerator implementation:
public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator
{
private List<T> list;
private int index;
private int version;
private T current;
internal Enumerator(List<T> list)
{
this.list = list;
this.index = 0;
this.version = list._version;
this.current = default(T);
return;
}
public bool MoveNext()
{
List<T> list;
list = this.list;
if (this.version != list._version)
{
goto Label_004A;
}
if (this.index >= list._size)
{
goto Label_004A;
}
this.current = list._items[this.index];
this.index += 1;
return 1;
Label_004A:
return this.MoveNextRare();
}
public T Current
{
get { return this.current; }
}
}
And here's my very barebone version:
internal struct DynamicArrayEnumerator<T> : IEnumerator<T> where T : class
{
private readonly T[] internalArray;
private readonly int lastIndex;
private int currentIndex;
internal DynamicArrayEnumerator(DynamicArray<T> dynamicArray)
{
internalArray = dynamicArray.internalArray;
lastIndex = internalArray.Length - 1;
currentIndex = -1;
}
public T Current
{
get { return internalArray[currentIndex]; }
}
public bool MoveNext()
{
return (++currentIndex <= lastIndex);
}
}
I know this is micro-optimization, but I'm actually interested in understanding why the List enumerator is so much faster than mine. Any ideas? Thanks!
Edit:
As requested; the DynamicArray class (the relevant parts):
The enumerator is an inner class in this.
public struct DynamicArray<T> : IEnumerable<T> where T : class
{
private T[] internalArray;
private int itemCount;
internal T[] Data
{
get { return internalArray; }
}
public int Count
{
get { return itemCount; }
}
public DynamicArray(int count)
{
this.internalArray = new T[count];
this.itemCount = 0;
}
public IEnumerator<T> GetEnumerator()
{
return new DynamicArrayEnumerator<T>(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
As for how I'm testing:
List<BaseClass> list = new List<BaseClass>(1000000);
DynamicArray<BaseClass> dynamicArray = new DynamicArray<BaseClass>(1000000);
// Code for filling with data omitted.
int numberOfRuns = 0;
float p1Total = 0;
float p2Total = 0;
while (numberOfRuns < 100)
{
PerformanceAnalyzer p1 = new PerformanceAnalyzer(() =>
{
int u = 0;
foreach (BaseClass b in list)
{
if (b.B > 100) // Some trivial task
u++;
}
});
p1.ExecuteAndClock();
p1Total += p1.TotalElapsedTicks;
PerformanceAnalyzer p2 = new PerformanceAnalyzer(() =>
{
int u = 0;
foreach (BaseClass b in dynamicArray)
{
if (b.B > 100) // Some trivial task
u++;
}
});
p2.ExecuteAndClock();
p2Total += p2.TotalElapsedTicks;
numberOfRuns++;
}
Console.WriteLine("List enumeration: " + p1Total / totalRuns + "\n");
Console.WriteLine("Dynamic array enumeration: " + p2Total / totalRuns + "\n");
The PerformanceAnalyzer class basically starts a Stopwatch, execute the supplied Action delegate, and then stop the Stopwatch afterwards.
Edit 2 (Quick answer to Ryan Gates):
There's a few reasons why I would want to roll my own, most importantly I need a very fast RemoveAt(int index) method.
Since I don't have to worry about the order of the list elements in my particular case, I can avoid the .Net built-in list's way of doing it:
public void RemoveAt(int index)
{
T local;
if (index < this._size)
{
goto Label_000E;
}
ThrowHelper.ThrowArgumentOutOfRangeException();
Label_000E:
this._size -= 1;
if (index >= this._size)
{
goto Label_0042;
}
Array.Copy(this._items, index + 1, this._items, index, this._size - index);
Label_0042:
this._items[this._size] = default(T);
this._version += 1;
return;
}
And instead using something along the lines of:
public void RemoveAt(int index)
{
// overwrites the element at the specified index with the last element in the array and decreases the item count.
internalArray[index] = internalArray[itemCount];
itemCount--;
}
Potencially saving enormous amounts of time in my case, if say the first 1000 elements in a long list have to be removed by index.
Okay, aside from benchmarking problems, here's how you can make your DynamicArray class more like List<T>:
public DynamicArrayEnumerator<T> GetEnumerator()
{
return new DynamicArrayEnumerator<T>(this);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
Now, code which knows it's working with a dynamic array can iterate with a DynamicArrayEnumerator<T> without any boxing, and without virtual dispatch. This is exactly what List<T> does. The compiler notices when a type implements the pattern in a custom manner, and will use the types involved instead of the interfaces.
With your current code, you're getting no benefit from creating a struct - because you're boxing it in GetEnumerator().
Try the above change and fix the benchmark to work for longer. I'd expect to see a big difference.

Does .NET have a built in IEnumerable for multiple collections?

I need an easy way to iterate over multiple collections without actually merging them, and I couldn't find anything built into .NET that looks like it does that. It feels like this should be a somewhat common situation. I don't want to reinvent the wheel. Is there anything built in that does something like this:
public class MultiCollectionEnumerable<T> : IEnumerable<T>
{
private MultiCollectionEnumerator<T> enumerator;
public MultiCollectionEnumerable(params IEnumerable<T>[] collections)
{
enumerator = new MultiCollectionEnumerator<T>(collections);
}
public IEnumerator<T> GetEnumerator()
{
enumerator.Reset();
return enumerator;
}
IEnumerator IEnumerable.GetEnumerator()
{
enumerator.Reset();
return enumerator;
}
private class MultiCollectionEnumerator<T> : IEnumerator<T>
{
private IEnumerable<T>[] collections;
private int currentIndex;
private IEnumerator<T> currentEnumerator;
public MultiCollectionEnumerator(IEnumerable<T>[] collections)
{
this.collections = collections;
this.currentIndex = -1;
}
public T Current
{
get
{
if (currentEnumerator != null)
return currentEnumerator.Current;
else
return default(T);
}
}
public void Dispose()
{
if (currentEnumerator != null)
currentEnumerator.Dispose();
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
if (currentIndex >= collections.Length)
return false;
if (currentIndex < 0)
{
currentIndex = 0;
if (collections.Length > 0)
currentEnumerator = collections[0].GetEnumerator();
else
return false;
}
while (!currentEnumerator.MoveNext())
{
currentEnumerator.Dispose();
currentEnumerator = null;
currentIndex++;
if (currentIndex >= collections.Length)
return false;
currentEnumerator = collections[currentIndex].GetEnumerator();
}
return true;
}
public void Reset()
{
if (currentEnumerator != null)
{
currentEnumerator.Dispose();
currentEnumerator = null;
}
this.currentIndex = -1;
}
}
}
Try the SelectMany extension method added in 3.5.
IEnumerable<IEnumerable<int>> e = ...;
foreach ( int cur in e.SelectMany(x => x)) {
Console.WriteLine(cur);
}
The code SelectMany(x => x) has the effect of flattening a collection of collections into a single collection. This is done in a lazy fashion and allows for straight forward processing as shown above.
If you only have C# 2.0 available, you can use an iterator to achieve the same results.
public static IEnumerable<T> Flatten<T>(IEnumerable<IEnumerable<T>> enumerable) {
foreach ( var inner in enumerable ) {
foreach ( var value in inner ) {
yield return value;
}
}
}
Just use the Enumerable.Concat() extension method to "concatenate" two IEnumerables. Don't worry, it doesn't actually copy them into a single array (as you might infer from the name), it simply allows you to enumerate over them all as if they were one IEnumerable.
If you have more than two then Enumerable.SelectMany() would be better.

Return an empty IEnumerator

I have an interface that, among other things, implements a "public IEnumerator GetEnumerator()" method, so I can use the interface in a foreach statement.
I implement this interface in several classes and in one of them, I want to return an empty IEnumerator. Right now I do this the following way:
public IEnumerator GetEnumerator()
{
ArrayList arr = new ArrayList();
return arr.GetEnumerator();
}
However I consider this an ugly hack, and I can't help but think that there is a better way of returning an empty IEnumerator. Is there?
This is simple in C# 2:
public IEnumerator GetEnumerator()
{
yield break;
}
You need the yield break statement to force the compiler to treat it as an iterator block.
This will be less efficient than a "custom" empty iterator, but it's simpler code...
There is an extra function in the framework:
public static class Enumerable
{
public static IEnumerable<TResult> Empty<TResult>();
}
Using this you can write:
var emptyEnumerable = Enumerable.Empty<int>();
var emptyEnumerator = Enumerable.Empty<int>().GetEnumerator();
You could implement a dummy class that implements IEnumerator, and return an instance of it:
class DummyEnumerator : IEnumerator
{
public object Current
{
get
{
throw new InvalidOperationException();
}
}
public bool MoveNext()
{
return false;
}
public void Reset()
{
}
}
I was curious and went a bit further. I made a test that checks how efficient the methods are comparing yield break, Enumerable.Emtpy and custom class.
You can check it out on dotnetfiddle https://dotnetfiddle.net/p5ZkUN or use the code below.
The result of one of the many dotnetfiddle runs using 190 000 iterations was:
Yield break: 00:00:00.0012208
Enumerable.Empty(): 00:00:00.0007815
EmptyEnumerator instance: 00:00:00.0010226
using System;
using System.Diagnostics;
using System.Collections;
using System.Linq;
public class Program
{
private const int Iterations = 190000;
public static void Main()
{
var sw = new Stopwatch();
IEnumerator enumerator1 = YieldBreak();
sw.Start();
for (int i = 0; i < Iterations; i++)
{
while(enumerator1.MoveNext())
{
throw new InvalidOperationException("Should not occur");
}
}
sw.Stop();
Console.WriteLine("Yield break: {0}", sw.Elapsed);
GC.Collect();
IEnumerator enumerator2 = Enumerable.Empty<object>().GetEnumerator();
sw.Restart();
for (int i = 0; i < Iterations; i++)
{
while(enumerator2.MoveNext())
{
throw new InvalidOperationException("Should not occur");
}
}
sw.Stop();
Console.WriteLine("Enumerable.Empty<T>(): {0}", sw.Elapsed);
GC.Collect();
var enumerator3 = new EmptyEnumerator();
sw.Restart();
for (int i = 0; i < Iterations; i++)
{
while(enumerator3.MoveNext())
{
throw new InvalidOperationException("Should not occur");
}
}
sw.Stop();
Console.WriteLine("EmptyEnumerator instance: {0}", sw.Elapsed);
}
public static IEnumerator YieldBreak()
{
yield break;
}
private class EmptyEnumerator : IEnumerator
{
//public static readonly EmptyEnumerator Instance = new EmptyEnumerator();
public bool MoveNext()
{
return false;
}
public void Reset()
{
}
public object Current { get { return null; } }
}
}
The way I use is to use the enumerator of an empty array:
public IEnumerator GetEnumerator() {
return new object[0].GetEnumerator();
}
It can also be used for generic IEnumerator or IEnumerable (use an array of the appropriate type)
You can implement IEnumerator interface and IEnumerable, and return false from MoveNext function of IEnumerable interfase
private class EmptyEnumerator : IEnumerator
{
public EmptyEnumerator()
{
}
#region IEnumerator Members
public void Reset() { }
public object Current
{
get
{
throw new InvalidOperationException();
}
}
public bool MoveNext()
{ return false; }
}
public class EmptyEnumerable : IEnumerable
{
public IEnumerator GetEnumerator()
{
return new EmptyEnumerator();
}
}
I wrote it like this:
public IEnumerator<T> GetEnumerator()
{
return this.source?.GetEnumerator() ??
Enumerable.Empty<T>().GetEnumerator();
}
You can make a NullEnumerator which implements the IEnumerator interface. You can just pass an instance off the NullEnumerator.
here is an example of an EmptyEnumerator
Found this question looking for the simplest way to get an empty enumerator. After seeing the answer comparing performance I decided to use the empty enumerator class solution, but mine is more compact than the other examples, and is a generic type, and also provides a default instance so you don't have to create new instances all the time, which should even further improve performance.
class EmptyEnumerator<T> : IEnumerator<T>
{
public readonly static EmptyEnumerator<T> value = new EmptyEnumerator<T>();
public T Current => throw new InvalidOperationException();
object IEnumerator.Current => throw new InvalidOperationException();
public void Dispose() { }
public bool MoveNext() => false;
public void Reset() { }
}

Question about yield return statement

Take the example here:
public static IEnumerable<BigInt> EvenNumbers(IEnumerable<BigInt> numbers)
{
foreach (BigInt number in numbers)
{
if (number % 2 == 0)
{
yield return number;
}
}
}
This will return only the values which match the criteria (n % 2 == 0). But what is the difference between yield return number; and return number;?
If I say yield return number, will it return each number to the calling function and so on? Where can I find some details on what goes on behind the scenes?
Thanks
"return" simply won't work here (since it would try to return a BigInt, and the method declares an IEnumerable<BigInt>. Jon Skeet has a good write-up of iterator blocks (what this is) in the free chapter 6 of C# in Depth (then buy the whole book - it really is worth it ;-p).
edit - here's a very rough version of what you would have to do in order to write this yourself; note that it doesn't quite do the same, but achieves the goal. I think you'll agree that the yield return version is easier!
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
static class Program
{
static void Main()
{
IEnumerable<int> source = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach (int value in EvenNumbers(source))
{
Console.WriteLine(value);
}
}
public static IEnumerable<int> EvenNumbers(IEnumerable<int> numbers)
{
return new EvenEnumerable(numbers);
}
class EvenEnumerable : IEnumerable<int>
{
private readonly IEnumerable<int> numbers;
public EvenEnumerable(IEnumerable<int> numbers) {
this.numbers = numbers;
}
public IEnumerator<int> GetEnumerator()
{
return new EvenEnumerator(numbers);
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class EvenEnumerator : IEnumerator<int>
{
private readonly IEnumerable<int> numbers;
public EvenEnumerator(IEnumerable<int> numbers)
{
this.numbers = numbers;
}
private int current;
void IEnumerator.Reset() { throw new NotSupportedException(); }
public int Current { get { return current; } }
object IEnumerator.Current { get { return Current; } }
IEnumerator<int> iter;
public bool MoveNext()
{
if (iter == null) iter = numbers.GetEnumerator();
while (iter.MoveNext())
{
int tmp = iter.Current;
if (tmp % 2 == 0)
{
current = tmp;
return true;
}
}
return false;
}
public void Dispose()
{
if (iter != null)
{
iter.Dispose();
iter = null;
}
}
}
}
Using yield return actually causes the compiler to create a simple IEnumerator class that does the work of the loop. The structure of the for loop actually determines the operations inside the MoveNext method that the compiler creates.
Check out this blog post for sample IL deconstruction

Categories