Check if a List<T>.Enumerator is valid

Started by
5 comments, last by Nypyren 10 years, 7 months ago

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.

Advertisement

Where is the enumerator coming from? If it's from your own code, meaning that you can control the circumstances under which the enumerator is generated, you could always use nullable types.

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.

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.

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

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.
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);
		}
	}
}

This topic is closed to new replies.

Advertisement