Edge cases:
";abc".LazySplit(";")will return an empty sequence. To match the behaviour of";abc".Split(new char[] { ';' })it should return the sequence{ "", "abc" }.";abc".LazySplit("")will return a sequence with a single item, the empty string. To match the behaviour of";abc".Split(new char[] { })it should return the sequence{ ";abc" }.
Here's how I would suggest writing it.
First, deal with the empty separator
if (separator.Length == 0)
{
yield return value;
yield break;
}
Then have two variables, start and end that refer to the start and end of the substring we want to extract.
var start = 0;
for (var end = value.IndexOf(separator); end != -1; end = value.IndexOf(separator, start))
{
yield return value.Substring(start, end - start);
start = end + separator.Length;
}
yield return value.Substring(start);
To make your unit tests match the behaviour of string.Split, you also want to change LazyStringSplit to have
var expected = new[] { "ab", "cd", "", "" };
and LazyStringSplitEmptyString to have
var expected = new string[] { "" };
If you want to test that your implementation matches the behaviour of string.Split, I would suggest introducing a helper method for the tests. Something like
var expected = value.Split(new string[] { separator }, StringSplitOptions.None);
CollectionAssert.AreEqual(expected, value.LazySplit(separator));