Jump to content
  • Advertisement
Sign in to follow this  
Grain

Check if a List<T>.Enumerator is valid

This topic is 2145 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In C# how can I check if a List enumerator is valid before using it? Valid meaning it has been attached to a List already. Since enumerator is a struct it's not comparable to null so that option is out. The .Current property can be null even if the enumerator is valid, for example if MoveNext() has not yet been called for the first time or if the end of the list has been reached, so checking that isn't helpful in all cases either.  

 

I can call MoveNext() in a try/catch block, which would tell me if it's valid or not, but if the the enumerator IS valid I don't wan't to move to the next item just yet. I would wan't to check if the .Current property if not null and then work with that item before calling MoveNext(). And I don't really like catching exceptions as part of preforming basic logic anyway, they should be only for error handling. 

Share this post


Link to post
Share on other sites
Advertisement

I have a custom container class that is arranged like a tree. Each element can have up-to 1 neighbor element and any number of children elements, these children are stored in a standard library List<T>.

 

Each element also has a  List<T>.Enumerator so that when I iterate through this container and come to the end of a branch and then back up it will remember which branch it was last down and go to the next branch next, if it exists.  Now not all all elements have children, in fact most don't, so for those I don't even bother creating a List<T> instance and there for don't have anything to attach the Enumerator to. 

Share this post


Link to post
Share on other sites
That sounds very odd. What is the purpose of the 0-or-1 neighbor element? Why do you keep track of the enumerator manually? What kind of traversal are you trying to perform?

These questions might be better answered if you posted the code. Edited by Nypyren

Share this post


Link to post
Share on other sites

What is the purpose of the 0-or-1 neighbor element?

 Same idea as a linked list. Only this can potentially branch. 
 

Why do you keep track of the enumerator manually?

Is there some method of keeping track of it automatically?
 

What kind of traversal are you trying to perform?

Move to the first child first, then to any of it's children/neighbors next ect, return to the parent when you reach the end, repeat for the next child until there are no more children, move to the neighbor.

public class FileParseElement
    {
        string token;
        FileParseElement Neighbor;
        List<FileParseElement> Children;
        List<FileParseElement>.Enumerator CurrentChild;


        public static FileParseElement BuildFullObjectStructure(ref List<string>.Enumerator ittr){...}
        public static FileParseElement BuildObjectSet(ref List<string>.Enumerator ittr){...}
        public string Token
        {
            get { return token; }
        }
        
        
        public FPE_Iterator GetIterator()
        {
            return new FPE_Iterator(this) { };
        }

        public class FPE_Iterator  //this IS a nested class 
        {
            FileParseElement Head;
            Stack<FileParseElement> ParrentStack;

            public FPE_Iterator(FileParseElement FPE)
            {
                ParrentStack = new Stack<FileParseElement>();
                Head = FPE;
            }

            public FileParseElement Current
            {
                get { return Head; }
            }

            public bool Movenext()
            {
                if (Head.Children != null)
                {
                    if (Head.CurrentChild != new List<FileParseElement>.Enumerator()) //compiler doesn't allow this
                    {
                        ParrentStack.Push(Head);
                        Head = Head.Children.GetEnumerator().Current;
                        return true;
                    }
                }
 
                if (Head.Neighbor != null  /*&& I have no children or finished tracversing them*/)
                {
                    Head = Head.Neighbor;
                    return true;
                }
                else
                {
                     //pop a parent off the stack and assign it to Head
                     return false;
                }
            } 
       } 
    }

Movenext() is what I'm working on now. It's far from compleet

Edited by Grain

Share this post


Link to post
Share on other sites
This is a pre-order (or post-order, haven't looked closely) tree traversal. One way to achieve this with C# is nesting yield. Take a look here. For big trees the disadvantage is the lot of temporary enumerators created. A solution is to use an explicit stack, like linked from that thread here (it uses a binary tree, but the principle applies).

Edit: Please excuse. I only see now you are using an explicit stack. Anyway, using yield makes the implementation easier, so I recommend using it. Edited by unbird

Share this post


Link to post
Share on other sites
OK, So 'Children' are the left branches and 'Neighbor' is the right?

Something like this will do depth-first pre-order traversal (haven't tested for typos/bugs):
 
public IEnumerable<FileParseElement> PreOrderTraversal()
{
	var stack = new Stack<FileParseElement>();

	if (Neighbor != null)
		stack.Push(Neighbor);

	stack.Push(this);
				
	while (stack.Count > 0)
	{
		var current = stack.Pop();
		yield return current;

		foreach (var child in current.Children)
		{
			yield return child;
			if (child.Neighbor != null)
				stack.Push(child.Neighbor);
		}
	}
}
Edited by Nypyren

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!