How it works
A batch processor often needs to continue after a single bad record while preserving evidence of the rejection. That policy should be explicit. An error in one record can be isolated, but an unexpected defect in the processor itself should not automatically be hidden as another ordinary input problem. Narrow exception handling helps express which failures the workflow has chosen to tolerate.
This example performs a deliberately small integer calculation for each prepared text value. It distinguishes malformed numeric text from a zero divisor and continues to later records after either expected failure. The loop itself owns the per-record boundary. Moving the try block outside the loop would change that policy by stopping the remaining work after the first handled exception.
Walk through the example. The first record parses as five and produces twenty. The zero record reaches integer division and throws DivideByZeroException, which becomes a zero-divisor message. The word bad throws FormatException during parsing, producing a different message. The final four still executes and produces twenty-five, demonstrating that earlier rejected records did not terminate the batch.
Watch the boundary. Catching Exception around everything and printing invalid would also hide programming defects, unsupported operations, and other failures that may require stopping. Catch only the failures the record contract actually expects. For common validation, TryParse and explicit zero checks may be clearer than exceptions; this sample is about the placement and specificity of a recovery boundary, not a rule to throw for every validation failure.
Practice independently. Rewrite the processor using TryParse and an explicit zero guard, keeping the same observable report. Then add an unexpected failure from a separate calculation function and decide whether it should propagate rather than being labeled as bad input. Record accepted and rejected counts, and test that a rejection in the middle of the batch does not suppress valid records after it.
A working example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
foreach (string text in new[] { "5", "0", "bad", "4" })
{
try
{
int divisor = int.Parse(text, CultureInfo.InvariantCulture);
Console.WriteLine($"value:{100 / divisor}");
}
catch (FormatException) { Console.WriteLine("rejected:format"); }
catch (DivideByZeroException) { Console.WriteLine("rejected:zero-divisor"); }
}
Expected output
value:20 rejected:zero-divisor rejected:format value:25
Put a recovery boundary around one record only when continuing is the intended batch policy.