Question: I have a huge string in the memory (a few hundred megabytes, there is no way I can load it partially), I wonder whether there is some easy way to split this string into lines divided by Environment.NewLine:
a) without duplicating this structure in the memory (if I use string.Split it will duplicate it)
b) with some default c# methods / minimum amount of efficient (when it comes to performance) code

Practically I would like to have a method, GetNextLineFromString.

Answer: 
You can try *enumerating* lines, e.g.

```
private static IEnumerable<string> LinesFromString(string value) {
  if (string.IsNullOrEmpty(value))
    yield break;

  int last = 0;

  while (true) {
    int next = value.IndexOf(Environment.NewLine, last);

    if (next < 0) {
      yield return value.Substring(last);

      yield break;
    }

    yield return value.Substring(last, next - last);

    last = next + Environment.NewLine.Length;
  }
}

```

**Demo:**

```
string text = string.Join(Environment.NewLine, 
  "ABC", 
  "D", 
  "", // <- Empty line
  "EF"
);

Console.Write(string.Join(";", LinesFromString(text)));

```

**Outcome:**

```
ABC;D;;EF

```

If you want `N`th line you can query `text` with a help of Linq:

```
int N = 1; // N is zero-based

string line = LinesFromString(text)
  .Skip(N - 1)
  .FirstOrDefault(); // Either Nth string or null

```

**Edit:** If you use *.Net Core 3.1*, *.Net Standard 2.1* or higher you can try representing long `string` as `ReadOnlyMemory<char>` and work with *slices* of it; e.g.

```
private static IEnumerable<ReadOnlyMemory<char>> LinesFromMemory(ReadOnlyMemory<char> value) {
  int last = 0;

  while (true) {
    int at = value.Span.Slice(last).IndexOf(Environment.NewLine);

    if (at < 0) {
      yield return value.Slice(last);

      yield break;
    }

    yield return value.Slice(last, at);

    last += at + Environment.NewLine.Length;
  }
} 

```

Then

```
string huge = string.Join(Environment.NewLine, 
  "ABC", 
  "D", 
  "", // <- Empty line
  "EF"
);

// Note, memory is not a string, but some kind of pointer (to huge) 
foreach (var memory in LinesFromMemory(huge.AsMemory())) {
  // Let's convert memory to string and print it out
  string st = memory.ToString();

  Console.Write(st);
  Console.Write(';'); 
}

```
Could you not save the string to a temp file, use `String.Spilt()` via a `StreamReader`, then, finally, delete the file?