How it works
Where filters each element independently, keeping every value whose predicate is true. TakeWhile instead returns an initial prefix and stops when the predicate first fails. The sample's negative marker splits those meanings: the positive three after the marker qualifies for Where but is outside the prefix produced by TakeWhile.
SkipWhile complements the prefix idea by skipping the initial matching run and then returning the remaining tail. Once it reaches negative one, it includes that value and the later three. It does not continue filtering each later value. These operators are about a boundary in an ordered sequence, not merely about a set of matching values.
Order is therefore part of their contract. Reordering the input can change which prefix is accepted and where the tail begins. A sorted measurement stream may make a threshold boundary meaningful; an unordered collection of independent records may require Where instead. Choose the operator that matches the data's ordering guarantees.
A common mistake is using TakeWhile to remove all invalid rows from an import. One invalid row would then prevent every later valid row from being processed. That behavior is correct only if the first failure genuinely terminates the accepted section, such as a protocol delimiter or a consecutive-valid-run calculation.
Practice with a sequence beginning with a negative value, a sequence containing only positives, and an empty sequence. Predict all three outputs for each input. Then move the negative marker to the end and explain why the matching prefix grows while the element-by-element filtering rule remains unchanged.
Finally, write a small parser for an ordered header section ending at a delimiter. Use TakeWhile to read the header and SkipWhile to locate the rest, then decide explicitly whether the delimiter itself belongs in the next stage. Boundary-sensitive operators are powerful when their stopping rule is documented and tested, rather than guessed from a convenient example.
A working example
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
int[] values = { 1, 2, -1, 3 };
Console.WriteLine(string.Join(",", values.TakeWhile(value => value > 0)));
Console.WriteLine(string.Join(",", values.Where(value => value > 0)));
Console.WriteLine(string.Join(",", values.SkipWhile(value => value > 0)));
Expected output
1,2 1,2,3 -1,3
TakeWhile stops permanently after the first predicate failure.