How to write GetEnumerator() for a generic class? - c#

I have a generic class in my program. Then I want to use an instance of class<T> in a foreach loop, but it needs to use a public GetEnumerator. How can I write a GetEnumerator() for foreach?
public class ReadStruct<T> where T : struct
{
MemoryTributary _ms = null;
public ReadStruct(MemoryTributary ms)
{
_ms = ms;
}
public T this[int Index]
{
get
{
if (Index < Count)
return _ms.Read<T>(Index);
return new T();
}
}
public int CountByteToStruct { get { return Marshal.SizeOf(typeof(T)); } }
public long Count { get { return _ms.Length / CountByteToStruct; } }
// it doesn't work!!
public IEnumerator<T> GetEnumerator()
{
return (IEnumerator<T>)this;
}
}

Implement IEnumerable<T>, it's not mandatory for use in foreach but it's best practice so you can cast your struct to IEnumerable<T> and get extension method support:
public class ReadStruct<T> : IEnumerable<T>
where T : struct
Then you can implement GetEnumerator using yield return and reusing your indexer:
public IEnumerator<T> GetEnumerator()
{
var count = Count;
for (var i = 0; i < count; ++i)
yield return this[i];
}

Related

Cannot yield even though the return type is IEnumerable<U>

Consider the following trivial example:
class Filter<T, U>
where T : IEnumerable<U>
where U : IEquatable<U>
{
private readonly U id;
public Filter(U id) => this.id = id;
public T Eval_A(T items)
{
foreach (var item in items)
if (item.Equals(id))
yield return item;
}
public IEnumerable<U> Eval_B(IEnumerable<U> items)
{
foreach (var item in items)
if (item.Equals(id))
yield return item;
}
}
Even though T is of type IEnumerable<U>, an error still occurs for T Eval_A(T items) as follows.
The body of 'accessor' cannot be an iterator block because 'type' is not an iterator interface type
MSDN said:
This error occurs if an iterator accessor is used but the return type is not one of the iterator interface types: IEnumerable, IEnumerable<T>, IEnumerator, IEnumerator<T>. To avoid this error, use one of the iterator interface types as a return type.
I think the return type does conforms to the requirement.
What am I missing here?
The return type of the method has to be exactly one of IEnumerable, IEnumerable<T>, IEnumerator or IEnumerator<T>, and not T, which is some type that implements IEnumerable<U>.
This is because the way that iterator methods work, is that the compiler generates a type implementing one of the above interfaces, with the MoveNext and Current correctly implemented so that it matches the behaviour of your method, and then it rewrites your method to return an instance of that type instead.
For example, for:
public IEnumerable<int> GetSingleDigitNumbersLoop()
{
int index = 0;
while (index < 10)
yield return index++;
}
The following is generated (seen using SharpLab.io):
[IteratorStateMachine(typeof(<GetSingleDigitNumbersLoop>d__0))]
public IEnumerable<int> GetSingleDigitNumbersLoop()
{
return new <GetSingleDigitNumbersLoop>d__0(-2);
}
[CompilerGenerated]
private sealed class <GetSingleDigitNumbersLoop>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator
{
private int <>1__state;
private int <>2__current;
private int <>l__initialThreadId;
private int <index>5__2;
int IEnumerator<int>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <GetSingleDigitNumbersLoop>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
}
private bool MoveNext()
{
int num = <>1__state;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
}
else
{
<>1__state = -1;
<index>5__2 = 0;
}
if (<index>5__2 < 10)
{
<>2__current = <index>5__2++;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <GetSingleDigitNumbersLoop>d__0(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<int>)this).GetEnumerator();
}
}
<GetSingleDigitNumbersLoop>d__0 is the type that implements IEnumerable<int> that GetSingleDigitNumbersLoop is rewritten to return instead.
Now, if GetSingleDigitNumbersLoop were declared to return some other type, like a type parameter T for example, the following wouldn't work:
public T GetSingleDigitNumbersLoop()
{
return new <GetSingleDigitNumbersLoop>d__0(-2);
}
Because <GetSingleDigitNumbersLoop>d__0 is not necessarily a T. In fact it almost never would be, because it is a compiler generated type!
See also: yield statement implementation

How can the enumerator encapsulate an array

I have an array of object with the starting length of 4, and each time the Add method reaches the length, the length doubles. The array implements IEnumerable:
public ObjectArrayCollection()
{
this.objectArray = new object[ObjectArrayCapacity];
Count = 0;
}
public int Count { get; protected set; }
public object this[int index]
{
get => this.objectArray[index];
set => this.objectArray[index] = value;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public ObjectArrayEnumeration GetEnumerator()
{
return new ObjectArrayEnumeration(objectArray);
}
and a class that implements IEnumeration:
public ObjectArrayEnumeration(object[] objectArray)
{
this.objectArray = objectArray;
}
public object Current
{
get
{
try
{
return objectArray;
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public bool MoveNext()
{
position++;
return position < objectArray.Length;
}
public void Reset()
{
position = -1;
}
The "possition < objectArray.length" condition is not good since objectArray can contain null if objects added don't fill the array. I sent the Count to the enumerator:
public ObjectArrayEnumeration GetEnumerator()
{
return new ObjectArrayEnumeration(objectArray, Count);
}
but since I need them both I was told that the enumerator should encapsulate objectArray.
I've tried this:
public IEnumerator GetEnumerator()
{
return objectArray.GetEnumerator();
}
but this way I don't enumerate the values. I am new with C# and learning and I've run out of ideas.
How can the enumerator encapsulate the objectArray?

How to make my InfiniteLoopingList class implement IEnumerable?

I am making a prototype application and for that I designed a class that behaves like an infinite looping list. That is, if my internal list contains 100 values, when I ask for the 101st value, I get the first, the 102nd yields the second, and so on, repeating.
So I would like to write the following code:
var slice = loopingListInstance.Skip(123).Take(5);
And for that I need to implement IEnumerable suitable, as I understand.
Here is my current code:
public class InfiniteLoopingList : IEnumerable<double>
{
double[] _values = File.ReadLines(#"c:\file.txt")
.Select(s => double.Parse(s, CultureInfo.InvariantCulture))
.ToArray();
int _size;
public InfiniteLoopingList()
{
_size = _values.Length;
}
public double this[int i]
{
get { return _values[i % _size]; }
set { _values[i % _size] = value; }
}
public IEnumerator<double> GetEnumerator()
{
return this.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
// ???? now what ?? :(
}
}
Since you implemented the indexer property, you could do it via the simplest way as follows:
public IEnumerator<double> GetEnumerator()
{
int i = 0;
while (true)
yield return this[i++];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
EDIT
Please notice, that this is not really infinite loop. This approach will only work until i = int.MaxValue. Thanks to #oleksii.
You don't need a class for this...
An extension method will do the trick:
public static class InfEx
{
public static IEnumerable<T> LoopForever<T>(this IEnumerable<T> src)
{
var data = new List<T>();
foreach(var item in src)
{
data.Add(item);
yield return item;
}
for(;;)
{
foreach(var item in data)
{
yield return item;
}
}
}
}
Now you can take a sequence and make it a looping, infinite sequence:
IEnumerable<Foo> mySeq = ...;
IEnumerable<Foo> infMySeq = mySeq.LoopForver();
IEnumerable<Foo> aSelectionOfInfMySeq = infMySeq.Skip(101).Take(5);
You can implement the IEnumerator interface:
class InifniteEnumerator<T> : IEnumerator<T> {
private int index = -1;
private IList<T> innerList;
private int repeatPos;
public InifniteEnumerator(IList<T> innerList, int repeatPos) {
this.innerList = innerList;
this.repeatPos = repeatPos;
}
public T Current {
get {
if (index == -1) {
throw new InvalidOperationException();
}
return this.innerList[index];
}
}
object IEnumerator.Current {
get {
return this.Current;
}
}
public void Dispose() {
}
public bool MoveNext() {
this.index++;
if (this.index == repeatPos) {
this.index = 0;
}
return true;
}
public void Reset() {
this.index = -1;
}
}
and then return an instance of it in the GetEnumerator methods:
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
public IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return new InifniteEnumerator(this, 100);
}

Is it possible to have C++-like generics in C#?

Perhaps this question was already asked million times but I couldn't find similar topic. Is it possible to write a generic class with multiple 'where'-s that will be checked in compile time? Here is what I have today
public class MsBitsEnumWrapper<TC, TE> : IEnumerable<TC>
{
internal class Helper : IEnumerator<TC>
{
private readonly TC[] _data;
private int _pos = -1;
private readonly IEnumBackgroundCopyJobs _jobs;
private readonly IEnumBackgroundCopyFiles _files;
// I miss C++ templates that allows me to implements this method in completelly generic fashion...
public Helper(TE source)
{
_jobs = source as IEnumBackgroundCopyJobs;
_files = source as IEnumBackgroundCopyFiles;
uint count = 0;
if (null != _jobs)
{
_jobs.GetCount(out count);
_jobs.Reset();
}
else
if (null != _files)
{
_files.GetCount(out count);
_files.Reset();
}
_data = new TC[count];
for (uint i = 0; i < count; ++i)
{
uint fetched = 0;
if (null != _jobs)
{
IBackgroundCopyJob job;
_jobs.Next(1, out job, ref fetched);
_data[i] = (TC)job;
}
else
if (null != _files)
{
IBackgroundCopyFile file;
_files.Next(1, out file, ref fetched);
_data[i] = (TC)file;
}
}
}
#region Implementation of IDisposable
public void Dispose() { }
#endregion
#region Implementation of IEnumerator
public bool MoveNext()
{
if (_pos < (_data.Length - 1))
{
_pos++;
return true;
}
return false;
}
public void Reset()
{
_pos = -1;
}
public TC Current
{
get { return _data[_pos]; }
}
object IEnumerator.Current
{
get { return Current; }
}
#endregion
}
private readonly Helper _enumerator;
public MsBitsEnumWrapper(TE source) { _enumerator = new Helper(source); }
#region Implementation of IEnumerable
public IEnumerator<TC> GetEnumerator() { return _enumerator; }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
#endregion
}
Obviously I don't like it because I have to have switch in run-time that detect the type of generic argument. Is it possible to have something like this ?
public class MsBitsEnumWrapper<TC, TE> : IEnumerable<TC>
where TE : IEnumBackgroundCopyJobs, IEnumBackgroundCopyFiles
where TC : IBackgroundCopyJob, IBackgroundCopyFile
{
internal class Helper : IEnumerator<TC>
{
private readonly TC[] _data;
private int _pos = -1;
private readonly TE _iface;
// I miss C++ templates that allows me to implements this method in completelly generic fashion...
public Helper(TE source)
{
_iface = source;
uint count;
_iface.GetCount(out count);
_iface.Reset();
_data = new TC[count];
for (uint i = 0; i < count; ++i)
{
uint fetched = 0;
TC job;
_iface.Next(1, out job, ref fetched);
_data[i] = job;
}
}
#region Implementation of IDisposable
public void Dispose() { }
#endregion
#region Implementation of IEnumerator
public bool MoveNext()
{
if (_pos < (_data.Length - 1))
{
_pos++;
return true;
}
return false;
}
public void Reset()
{
_pos = -1;
}
public TC Current
{
get { return _data[_pos]; }
}
object IEnumerator.Current
{
get { return Current; }
}
#endregion
}
private readonly Helper _enumerator;
public MsBitsEnumWrapper(TE source) { _enumerator = new Helper(source); }
#region Implementation of IEnumerable
public IEnumerator<TC> GetEnumerator() { return _enumerator; }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
#endregion
}
I realize that it won't work if generic is defined with TE=IEnumBackgroundCopyJobs and TC=IBackgroundCopyFile, but since I'm the one who defines TE and TC and function prototypes of given interfaces are the same it would be nice to have it work this way.
Or may be there is another way to simplify current code ?
Thanks!
As JaredPar indicated, you can't do this in C#. The choices are to use delegates, or go old school with using an abstract base class.
My implementation below take advantage of 'yield return' to cut down on the implementation of IEnumerable.
#if USE_DELEGATES
public class MsBitsEnum<T> : IEnumerable<T>
{
Action _reset;
Func<T> _next;
Func<int> _count;
public MsBitsEnum(Action reset, Func<T> next, Func<int> count)
{
_reset = reset;
_next = next;
_count = count;
}
public IEnumerator<T> GetEnumerator()
{
_reset();
int count = _count();
for (int i = 0; i < count; ++i)
yield return _next();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class MsBitsJobs : MsBitsEnum<IBackgroundCopyJob>
{
public MsBitsJobs(IEnumBackgroundCopyJobs jobs)
: base(() => jobs.Reset(),
() =>
{
IBackgroundCopyJob job = null;
uint fetched = 0;
jobs.Next(1, out job, out fetched);
return fetched == 1 ? job : null;
},
() =>
{
uint count;
jobs.GetCount(out count);
return (int) count;
})
{
}
}
public class MsBitsFiles : MsBitsEnum<IBackgroundCopyFile>
{
public MsBitsFiles(IEnumBackgroundCopyFiles files)
: base(() => files.Reset(),
() =>
{
IBackgroundCopyFile file = null;
uint fetched = 0;
files.Next(1, out file, out fetched);
return fetched == 1 ? file : null;
},
() =>
{
uint count;
files.GetCount(out count);
return (int)count;
})
{
}
}
#else // !USE_DELEGATES
public abstract class MsBitsEnum<T> : IEnumerable<T>
{
protected abstract void Reset();
protected abstract bool Next(out T item);
public IEnumerator<T> GetEnumerator()
{
T item;
Reset();
while (Next(out item))
yield return item;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class MsBitsJobs : MsBitsEnum<IBackgroundCopyJob>
{
IEnumBackgroundCopyJobs _jobs;
protected override void Reset()
{
_jobs.Reset();
}
protected override bool Next(out IBackgroundCopyJob job)
{
uint fetched;
_jobs.Next(1, out job, out fetched);
return fetched == 1;
}
public MsBitsJobs(IEnumBackgroundCopyJobs jobs)
{
_jobs = jobs;
}
}
public class MsBitsFiles : MsBitsEnum<IBackgroundCopyFile>
{
IEnumBackgroundCopyFiles _files;
protected override void Reset()
{
_files.Reset();
}
protected override bool Next(out IBackgroundCopyFile file)
{
uint fetched;
_files.Next(1, out file, out fetched);
return fetched == 1;
}
public MsBitsFiles(IEnumBackgroundCopyFiles files)
{
_files = files;
}
}
#endif // !USE_DELEGATES
It sounds like what you're asking is if C# supports structural typing in generics in the same way that C++ does for templates. The answer is No.
C++ templates aren't fully evaluated for correctness until the member functions are used with a given generic instantiation. C# generics on the other hand are fully evaluated on their own when they are compiled. It leaves no room for structural / match by name typing.
There are a couple of approaches you could take here. The more laborous approach is to create another interface for the GetCount and Reset functions. Then create wrapper types for the two interfaces to plug into these methods. This is a bit tedious though after a while.
My personal preference is to solve this problem with delegates.
public Helper(TE source, Func<TE,count> getCount, Action<TE> reset)
{
_iface = source;
uint count = getCount(_iface);
reset(_iface);
...
}

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() { }
}

Categories