private static void Skip(ref EitherContext <C2, T, C> context, out Option <T> next)
        {
            context.bd.DetectBacktrack();

            if (context.needsMove)
            {
                if (context.isLeft)
                {
                    context.left.skip(ref context.left.context, out context.left.current);
                }
                else
                {
                    context.right.skip(ref context.right.context, out context.right.current);
                }
            }
            else
            {
                context.needsMove = true;
            }

            next = context.isLeft ? context.left.current : context.right.current;

            if (!next.isSome)
            {
                context.bd.Release();
            }
        }
        private static void Remove(ref EitherContext <C2, T, C> context, out Option <T> next)
        {
            context.bd.DetectBacktrack();

            context.needsMove = false;
            if (context.isLeft)
            {
                context.left.remove(ref context.left.context, out context.left.current);
            }
            else
            {
                context.right.remove(ref context.right.context, out context.right.current);
            }
            Skip(ref context, out next);
        }
        private static void Dispose(ref EitherContext <C2, T, C> context, out Option <T> next)
        {
            next = Option <T> .None;

            context.bd.Release();

            if (context.isLeft)
            {
                context.left.dispose(ref context.left.context, out context.left.current);
            }
            else
            {
                context.right.dispose(ref context.right.context, out context.right.current);
            }
        }