This code is not compiling, and it's throwing the following error:
The type 'TestesInterfaces.MyCollection' already contains a definition for 'Current'
But when I delete the ambiguous method, it keeps giving other errors.
Can anyone help?
public class MyCollection<T> : IEnumerator<T>
{
private T[] vector = new T[1000];
private int actualIndex;
public void Add(T elemento)
{
this.vector[vector.Length] = elemento;
}
public bool MoveNext()
{
actualIndex++;
return (vector.Length > actualIndex);
}
public void Reset()
{
actualIndex = -1;
}
void IDisposable.Dispose() { }
public Object Current
{
get
{
return Current;
}
}
public T Current
{
get
{
try
{
T element = vector[actualIndex];
return element;
}
catch (IndexOutOfRangeException e)
{
throw new InvalidOperationException(e.Message);
}
}
}
}
I think you're misunderstanding IEnumerator<T>. Typically, collections implement IEnumerable<T>, not IEnumerator<T>. You can think of them like this:
When a class implements IEnumerable<T>, it is stating "I am a collection of things that can be enumerated."
When a class implements IEnumerator<T>, it is stating "I am a thing that enumerates over something."
It is rare (and probably wrong) for a collection to implement IEnumerator<T>. By doing so, you're limiting your collection to a single enumeration. If you try to loop through the collection within a segment of code that's already looping through the collection, or if you try to loop through the collection on multiple threads simultaneously, you won't be able to do it because your collection is itself storing the state of the enumeration operation. Typically, collections (implementing IEnumerable<T>) return a separate object (implementing IEnumerator<T>) and that separate object is responsible for storing the state of the enumeration operation. Therefore, you can have any number of concurrent or nested enumerations because each enumeration operation is represented by a distinct object.
Also, in order for the foreach statement to work, the object after the in keyword, must implement IEnumerable or IEnumerable<T>. It will not work if the object only implements IEnumerator or IEnumerator<T>.
I believe this is the code you're looking for:
public class MyCollection<T> : IEnumerable<T>
{
private T[] vector = new T[1000];
private int count;
public void Add(T elemento)
{
this.vector[count++] = elemento;
}
public IEnumerator<T> GetEnumerator()
{
return vector.Take(count).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
You need to define the interface the current is implementing.
Object IEnumerator.Current
{
//
}
public T Current
{
//
}
This way your class has 2 Current properties. but you can access them both.
MyCollection<string> col = new MyCollection<string>();
var ienumeratort = col.Current; //Uses IEnumerator<T>
var ienumerator = (IEnumerator)col.Current; //uses IEnumerator
I think with C# 2.0 onwards, you have a very easy way of implementing iterator and compiler does a lot of heavy lifting behind the scene by creating state machine. It's worth looking into it. Having said that, in that case your implementation would look something below:
public class MyCollection<T>
{
private T[] vector = new T[1000];
private int actualIndex;
public void Add(T elemento)
{
this.vector[vector.Length] = elemento;
}
public IEnumerable<T> CreateEnumerable()
{
for (int index = 0; index < vector.Length; index++)
{
yield return vector[(index + actualIndex)];
}
}
}
I am not sure about the purpose of actualIndex though - but i hope you get the idea.
After proper initialization of MyCollection, below is snippet somewhat looks like from consumer perspective:
MyCollection<int> mycoll = new MyCollection<int>();
foreach (var num in mycoll.CreateEnumerable())
{
Console.WriteLine(num);
}
Related
I'm not used to write C# code, only Java and Python.
Now I found some code example for an algorithm which is only available in C#.
There is one structure I don't understand, it is the Enumerator.
HashSet<Node>.Enumerator enumerator = hashSet.GetEnumerator();
enumerator.MoveNext();
Item next = enumerator.Current;
So Item is the data type stored in the HashSet hashSet. Is this equal to a for-loop iterating over a HashSet or how else can that be translated into python or java?
GetEnumerator() methods are presented in some data structures in C# such as List, Set, etc. It enables doing iteration through. Actually, foreach internally makes use of it.
foreach statement is to iterate through the elements of certain data structures. A foreach can be used when all of the following conditions hold:
The data structure implements either IEnumerable(which is to
satisfy legacy codes before generics) or IEnumerable<T> for some
type T.
You do not need to know the locations in the data structure of the
individual elements.
For example, the string class implements both IEnumerable and IEnumerable<Char>.
The IEnumerable<T> interface implies the data structure requires two methods:
public IEnumerator<T> GetEnumerator()
IEnumerator IEnumerable.GetEnumerator()
The latter method is required only because IEnumerable<T> is a subtype of IEnumerable, and that interface requires a GetEnumerator method that returns a non-generic IEnumerator. Both of these methods should return the same object; hence, because IEnumerator<T> is also a subtype of IEnumerator, this method can simply call the first method:
System.Collections.IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
As you can see, the IEnumerable.GetEnumerator() method returns a reference to another interface named System.Collections.IEnumerator. This interface provides the infrastructure to allow the caller to traverse the internal objects contained by the IEnumerable-compatible container:
public interface IEnumerator
{
bool MoveNext (); // Advance the internal position of the cursor.
object Current { get;} // Get the current item (read-only property).
void Reset (); // Reset the cursor before the first member.
}
Let's exemplify it.
public class PowersOfThree : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
return new PowersOfThreeEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
internal class PowersOfThreeEnumerator : IEnumerator<int>
{
private int index = 0;
public int Current
{
get { return (int)System.Math.Pow(3, index); }
}
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
index++;
if (index > 10)
return false;
else
return true;
}
public void Reset()
{
index = 0;
}
public void Dispose()
{
}
}
public class Test
{
public static void Main(string[] str)
{
var p2 = new PowersOfThree();
foreach (int p in p2)
{
System.Console.WriteLine(p);
}
}
}
Current method returns the same element until MoveNext method is called. The initial index is 0 each MoveNext method increments the index from 1 to 10, inclusively, then it returns false. When the enumerator is at this position, subsequent calls to MoveNext also return false.
Do you see that what happened to Current when MoveNext returned false? Can you set Current to the first element of the collection again?
If you don't reinstantiate new enumerator, no.
I have to create my own circular list, I using the generic one.
first i create the Node<D> class which represents the data and the next of the element
private class Node<D> {
public D info;
public Node<D> next;
public Node() {
}
public Node(D p) {
info = p;
}
}
To create the circular list, I create the circularList<T> class. this class using Node<> as item of the element.
Here is the CircularList<T> class
class CircularList<T> : IEnumerable<T> {
public Node<T> start;
public Node<T> rear;
public int count = 0;
public CircularList(T firstItem) {
start = new Node<T>(firstItem);
rear = start;
rear.next = start;
}
public void Insert(T newItem) {
//Inserting code here
}
public void Update(T oldItem, T newItem) {
//Updating code is here
}
public void Delete(T theItem) {
//deleting code is here
}
}
when I start to loop using foreach
foreach(string item in CircularList<string>){
}
I got an error says that the circularlist class needs GetEnumerator().
Actually I can loop all of my circular list, but I am using do-while and I need Node<T> to start the loop. but I don't want using Node and do-while.
How do I create the GetEnumerator()?
Any help appreciated. :)
Thank you
Note: I really-really don't understand about IEnumerable and those things, please go easy with the example and explanation.
You need to implement GetEnumerator() method from IEnumerable for the foreach to work.
Use something like following:
public class CircularList<T> : IEnumerable<T>
{
private List<T> mylist = new List<T>();
public T this[int index]
{
get
{
return this.mylist[index];
}
set
{
this.mylist.Insert(index, value);
}
}
public IEnumerator<T> GetEnumerator()
{
return this.mylist.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
mylist maintains the list of type T which you would insert, update and delete.
EDIT
myList is just the backing storage of your "custom" list. As long as you are implementing your underlying functionality correctly, myList could be array, arraylist and so on.
For simplicity, I've used List<T> here which already implements the interface IEnumerable<T> and IEnumerator<T>( notice IEnumera**tor** not IEnumerable).
See this answer for more details on the difference between IEnumerator and IEnumerable
Moreover, The foreach statement hides the complexity of the enumerators.
See IEnumerator for more details.
The compiler turns the foreach into something like this:
CircularList<string> testList=new CircularList<string>();
IEnumerator testEnumerator= testList.GetEnumerator();
while (testEnumerator.MoveNext())
{
string yourForEachIteratorVariable = (string)testEnumerator.Current
...
}
Please note that the codes here are only for the illustration purposes. You could/should modify to make it more flexible and "performant" according to your need/requirement.
And for linked list, you don't need a backing List<T>, you could simply add/insert on your head node and implement GetEnumerator() something like below:
public IEnumerator<T> GetEnumerator()
{
var node = start;
while(node != null)
{
yield return node.info;
node = node.next;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
I have a user defined class that I want to create a public List as part of. I want the List to be a List of delegate functions that I can add to and set each List Member to a delegate function. I want this list of functions to be part of the class I instantiate, so it follows the instance of the class as I pass it to other functions. I need the ability to call the delegated functions via a foreach loop, so it also has to be IEnumberable.
I've been trying for several hours, what I have may or may not do part of the job. When it started looking like I needed to write my own IEnumberation routines for the custom List, I realize I was in way over my head and came here.
This is the code I have:
public delegate List<ChartTestModel> MyDelegate<T>(T i);
public class DelegateList<T>
{
public void Add(MyDelegate<T> del)
{
imp.Add(del);
}
public void CallDelegates(T k)
{
foreach (MyDelegate<T> del in imp)
{
del(k);
}
}
private List<MyDelegate<T>> imp = new List<MyDelegate<T>>();
}
I don't even know if this does what I want it to or not. I know I can't ForEach through it, though. It's written entirely from pieced together code from looking on Google. I barely understand what it's supposed to do.
I don't see why you need a custom class at all. Just use List<T> where T is whatever delegate type.
List<Action> actions = new List<Action>();
actions.Add(() => blah blah);
actions.Add(Whatever); // Whatever() is a method
// now run them all
actions.ForEach(a => a());
IEnumerable<T> is simple to implement, particularly when you have a collection as a member of the class. All you need to do is define appropriate GetEnumerator methods, and the easiest thing to do is return the enumerator of the underlying collection.
class YourClass : IEnumerable<SomeClass>
{
List<SomeClass> list = ...
public IEnumerator<SomeClass> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Here, you implement methods for implicitly for IEnumerable<T> and explicitly for IEnumerable. (You have to implement both as IEnumerable<T> inherits IEnumerable.)
For your specific class, you might have
public class DelegateList<T> : IEnumerable<MyDelegate<T>>
{
// ...other class details
private List<MyDelegate<T>> imp = new List<MyDelegate<T>>();
public IEnumerator<MyDelegate<T>> GetEnumerator()
{
return imp.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
I hope this is userful to you.
static void Main(string[] args)
{
var delegateFuncs = new List<Func<string , string>> {
l1=>{ return "at1:" + l1;} ,
l2=>{ return "at2:" + l2;} ,
l3=>{ return "at3:" + l3;} ,
l4=>{ return "at4:" + l4;}
};
string parameter = "test";
foreach (var f in delegateFuncs)
{
Console.WriteLine(f(parameter));
}
Console.ReadLine();
}
I assume the following sample gives a best practice that we should follow when we implement the IEnumerable interface.
https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerator.movenext
Here is the question:
Why should we provide two version of Current method?
When the version ONE (object IEnumerator.Current) is used?
When the version TWO (public Person Current ) is used?
How to use PeopleEnum in the foreach statement. // updated
public class PeopleEnum : IEnumerator
{
public Person[] _people;
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
public PeopleEnum(Person[] list)
{
_people = list;
}
public bool MoveNext()
{
position++;
return (position < _people.Length);
}
public void Reset()
{
position = -1;
}
// explicit interface implementation
object IEnumerator.Current /// **version ONE**
{
get
{
return Current;
}
}
public Person Current /// **version TWO**
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
The IEnumerator.Current is an explicit interface implementation.
You can only use it if you cast the iterator to an IEnumerator (which is what the framework does with foreach). In other cases, the second version will be used.
You will see that it returns object and actually uses the other implementation which returns a Person.
The second implementation is not required per se by the interface, but is there as a convenience and in order to return the expected type instead of object.
Long-form implementation of IEnumerator is no longer necessary:
public class PeopleEnum : IEnumerable
{
public Person[] _people;
public PeopleEnum(Person[] list)
{
_people = list;
}
public IEnumerator GetEnumerator()
{
foreach (Person person in _people)
yield return person;
}
}
And to further bring it into the 21st century, don't use the non-generic IEnumerable:
public class PeopleEnum : IEnumerable<Person>
{
public Person[] _people;
public PeopleEnum(Person[] list)
{
_people = list;
}
public IEnumerator<Person> GetEnumerator()
{
foreach (Person person in _people)
yield return person;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I suspect the reason is that this code example was derived from an example class implementing IEnumerator<T> - if the example class PeopleEnum implemented IEnumerator<T> this approach would be required: IEnumerator<T> inherits IEnumerator so you have to implement both interfaces when implementing IEnumerator<T>.
The implementation of the non-generic IEnumerator requires Current to return object - the strongly typed IEnumerator<T> on the other hand requires Current to return an instance of type T - using explicit and direct interface implementation is the only way to fulfill both requirements.
It is there for convenience, eg. using the PeopleEnum.Current in a typesafe way in a while(p.MoveNext()) loop, not explicitly doing a foreach enumeration.
But the only thing you need to do is implement the interface, you could do it implicitly if you wish, however is there a reason for it? If I wanted to use MovePrevious on the class? Would it be cool if I should cast(unbox) the object to Person?
If you think the class could be extended with more manipulation methods the Person Current is a cool thing.
Version two isnt part of the interface. You have to satisfy the interface requirements.
Can someone share a simple example of using the foreach keyword with custom objects?
Given the tags, I assume you mean in .NET - and I'll choose to talk about C#, as that's what I know about.
The foreach statement (usually) uses IEnumerable and IEnumerator or their generic cousins. A statement of the form:
foreach (Foo element in source)
{
// Body
}
where source implements IEnumerable<Foo> is roughly equivalent to:
using (IEnumerator<Foo> iterator = source.GetEnumerator())
{
Foo element;
while (iterator.MoveNext())
{
element = iterator.Current;
// Body
}
}
Note that the IEnumerator<Foo> is disposed at the end, however the statement exits. This is important for iterator blocks.
To implement IEnumerable<T> or IEnumerator<T> yourself, the easiest way is to use an iterator block. Rather than write all the details here, it's probably best to just refer you to chapter 6 of C# in Depth, which is a free download. The whole of chapter 6 is on iterators. I have another couple of articles on my C# in Depth site, too:
Iterators, iterator blocks and data pipelines
Iterator block implementation details
As a quick example though:
public IEnumerable<int> EvenNumbers0To10()
{
for (int i=0; i <= 10; i += 2)
{
yield return i;
}
}
// Later
foreach (int x in EvenNumbers0To10())
{
Console.WriteLine(x); // 0, 2, 4, 6, 8, 10
}
To implement IEnumerable<T> for a type, you can do something like:
public class Foo : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
yield return "x";
yield return "y";
}
// Explicit interface implementation for nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator(); // Just return the generic version
}
}
(I assume C# here)
If you have a list of custom objects you can just use the foreach in the same way as you do with any other object:
List<MyObject> myObjects = // something
foreach(MyObject myObject in myObjects)
{
// Do something nifty here
}
If you want to create your own container you can use the yield keyword (from .Net 2.0 and upwards I believe) together with the IEnumerable interface.
class MyContainer : IEnumerable<int>
{
private int max = 0;
public MyContainer(int max)
{
this.max = max;
}
public IEnumerator<int> GetEnumerator()
{
for(int i = 0; i < max; ++i)
yield return i;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
And then use it with foreach:
MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
Console.WriteLine(i);
From MSDN Reference:
The foreach statement is not limited to IEnumerable types and can be applied to an instance of any type that satisfies the following conditions:
has the public parameterless GetEnumerator method whose return type is either class, struct, or interface type,
the return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is Boolean.
If you declare those methods, you can use foreach keyword without IEnumerable overhead. To verify this, take this code snipped and see that it produces no compile-time error:
class Item
{
public Item Current { get; set; }
public bool MoveNext()
{
return false;
}
}
class Foreachable
{
Item[] items;
int index;
public Item GetEnumerator()
{
return items[index];
}
}
Foreachable foreachable = new Foreachable();
foreach (Item item in foreachable)
{
}