Summary
Every cipher writes its output with File.WriteAllTextAsync(...) but never awaits the returned Task (the enclosing encode/decode methods are synchronous void). This is a fire-and-forget call: the write may not have flushed by the time the method returns, and any I/O exception is swallowed silently. The synchronous File.WriteAllText(...) should be used instead.
Why it's a bug
- Race / data loss: the process can continue (or exit) before the async write completes. This is exactly the kind of round-trip (encode → immediately decode) the app performs; results can read stale or partial output.
- Swallowed errors: an exception in the unawaited
Task (e.g. file locked, permissions) is never observed — the user sees a "success" message while nothing was written.
- No async benefit is gained anyway, since the call sites are synchronous and single-threaded.
Affected locations (12 calls across 6 ciphers)
cryptography/HistoricCiphers/CaesarCipher.cs:43, 50
cryptography/HistoricCiphers/VigenereCipher.cs:48, 56
cryptography/HistoricCiphers/SimpleSubCipher.cs:48, 56
cryptography/HistoricCiphers/SimpleTranspositionCipher.cs:46, 55
cryptography/HistoricCiphers/RailFenceCipher.cs:49, 63
cryptography/HistoricCiphers/PlayfairCipher.cs:59, 74
Proposed fix
Replace File.WriteAllTextAsync(writeToFile, output) with the synchronous File.WriteAllText(writeToFile, output) at all call sites. Simplest, correct, and matches the synchronous nature of these methods — no async/await plumbing needed for a single-threaded console app.
Acceptance criteria
Summary
Every cipher writes its output with
File.WriteAllTextAsync(...)but never awaits the returnedTask(the enclosingencode/decodemethods are synchronousvoid). This is a fire-and-forget call: the write may not have flushed by the time the method returns, and any I/O exception is swallowed silently. The synchronousFile.WriteAllText(...)should be used instead.Why it's a bug
Task(e.g. file locked, permissions) is never observed — the user sees a "success" message while nothing was written.Affected locations (12 calls across 6 ciphers)
cryptography/HistoricCiphers/CaesarCipher.cs:43, 50cryptography/HistoricCiphers/VigenereCipher.cs:48, 56cryptography/HistoricCiphers/SimpleSubCipher.cs:48, 56cryptography/HistoricCiphers/SimpleTranspositionCipher.cs:46, 55cryptography/HistoricCiphers/RailFenceCipher.cs:49, 63cryptography/HistoricCiphers/PlayfairCipher.cs:59, 74Proposed fix
Replace
File.WriteAllTextAsync(writeToFile, output)with the synchronousFile.WriteAllText(writeToFile, output)at all call sites. Simplest, correct, and matches the synchronous nature of these methods — noasync/awaitplumbing needed for a single-threaded console app.Acceptance criteria
Task/ fire-and-forget calls remain (grep WriteAllTextAsyncreturns nothing inHistoricCiphers/)dotnet buildclean; all tests pass