C# beats 100% with comments
\npublic class CombinationIterator {\n    // stores an indicies of characters for current combination\n    int[] order;\n    string characters;\n    bool hasNex
```\npublic class CombinationIterator {\n    // stores an indicies of characters for current combination\n    int[] order;\n    string characters;\n    bool hasNext;\n    \n    public CombinationIterator(string characters, int combinationLength) {\n        // first combination always exists for given requirements and equals to initial character set\n        order = new int[combinationLength];\n        this.characters = characters;\n        hasNext = true;\n        \n        for (var i = 0; i < characters.Length && i < order.Length; i++) {\n            order[i] = i;\n        }\n    }\n    \n    public string Next() {\n        // using String Builder to prevent multiple allocations for string concatenation\n        var sb = new StringBuilder();\n        \n        // retrieving current combination\n        for (var i = 0; i < order.Length; i++) {\n            sb.Append(characters[order[i]]);\n        }\n        \n        // if next combination won\'t be found set a flag\n        hasNext = false;\n        \n        // calculating next combination:\n        // 1. Take rightmost order array element which could be moved "righter" (i.e. responds to other combinations)\n        // 2. Moving current element should also reset "righter" elements, which should also be a valid combinations (i.e. every order element is greater than previous but less than characters set size).\n        // 3. If combination by moving current is invalid try another element from the left\n        // 4. If there are no elements to the left, but combination couldn\'t be formed - set hasNext flag to false (which is implemented first, but finding valid combination set it to true)\n        for (var i = order.Length - 1; i >= 0; i--) {\n            if (order[i] < characters.Length) {\n                order[i]++;\n                // recalculate rightmost elements\n                var prev = order[i];\n                for (var j = i + 1; j < order.Length; j++) {\n                    order[j] = ++prev;\n                }\n                \n                if (prev >= characters.Length) {\n                    continue;\n                }\n                \n                hasNext = true;\n                break;\n            }\n        }\n        \n        return sb.ToString();\n    }\n\n    public bool HasNext() {\n        // using flag instead of recalculating that no new combination is available\n        // also this differs from MoveNext since it shouldn\'t change state\n        return hasNext;\n    }\n}\n```
[]