Skip to content

Commit e82d50c

Browse files
authored
refactor: Parameter validation in "async"/"await" methods should be wrapped (#894)
This PR refactors async methods to follow the best practice of wrapping parameter validation in a synchronous outer method with an inner async implementation. This pattern ensures that parameter validation (like null checks) happens immediately when the method is called, rather than being deferred until the async state machine starts executing. ### Key Changes: - Async methods are split into synchronous outer methods that perform parameter validation and asynchronous inner implementation methods - Parameter validation exceptions are thrown synchronously before any async operations begin - Inner async methods use abbreviated parameter names to avoid closure capture of outer parameters
1 parent 4d4a43e commit e82d50c

File tree

2 files changed

+46
-29
lines changed

2 files changed

+46
-29
lines changed

Source/Testably.Abstractions.Compression/ZipArchiveEntryWrapper.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,31 +109,41 @@ public void ExtractToFile(string destinationFileName, bool overwrite)
109109

110110
#if FEATURE_COMPRESSION_ASYNC
111111
/// <inheritdoc cref="IZipArchiveEntry.ExtractToFileAsync(string, CancellationToken)" />
112-
public async Task ExtractToFileAsync(string destinationFileName, CancellationToken cancellationToken = default)
112+
public Task ExtractToFileAsync(string destinationFileName, CancellationToken cancellationToken = default)
113113
{
114114
if (destinationFileName == null)
115115
{
116116
throw new ArgumentNullException(nameof(destinationFileName));
117117
}
118118

119-
await Execute.WhenRealFileSystemAsync(FileSystem,
120-
async () => await _instance.ExtractToFileAsync(destinationFileName, cancellationToken),
121-
() => ZipUtilities.ExtractToFile(this, destinationFileName, false));
119+
return ExtractToFileImplAsync(destinationFileName, cancellationToken);
120+
121+
async Task ExtractToFileImplAsync(string d, CancellationToken c)
122+
{
123+
await Execute.WhenRealFileSystemAsync(FileSystem,
124+
async () => await _instance.ExtractToFileAsync(d, c),
125+
() => ZipUtilities.ExtractToFile(this, d, false));
126+
}
122127
}
123128
#endif
124129

125130
#if FEATURE_COMPRESSION_ASYNC
126131
/// <inheritdoc cref="IZipArchiveEntry.ExtractToFileAsync(string, bool, CancellationToken)" />
127-
public async Task ExtractToFileAsync(string destinationFileName, bool overwrite, CancellationToken cancellationToken = default)
132+
public Task ExtractToFileAsync(string destinationFileName, bool overwrite, CancellationToken cancellationToken = default)
128133
{
129134
if (destinationFileName == null)
130135
{
131136
throw new ArgumentNullException(nameof(destinationFileName));
132137
}
133138

134-
await Execute.WhenRealFileSystemAsync(FileSystem,
135-
async () => await _instance.ExtractToFileAsync(destinationFileName, overwrite, cancellationToken),
136-
() => ZipUtilities.ExtractToFile(this, destinationFileName, overwrite));
139+
return ExtractToFileImplAsync(destinationFileName, overwrite, cancellationToken);
140+
141+
async Task ExtractToFileImplAsync(string d, bool o, CancellationToken c)
142+
{
143+
await Execute.WhenRealFileSystemAsync(FileSystem,
144+
async () => await _instance.ExtractToFileAsync(d, o, c),
145+
() => ZipUtilities.ExtractToFile(this, d, o));
146+
}
137147
}
138148
#endif
139149

Source/Testably.Abstractions.Compression/ZipArchiveWrapper.cs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -166,30 +166,34 @@ public void ExtractToDirectory(string destinationDirectoryName, bool overwriteFi
166166

167167
#if FEATURE_COMPRESSION_ASYNC
168168
/// <inheritdoc cref="IZipArchive.ExtractToDirectoryAsync(string, CancellationToken)" />
169-
public async Task ExtractToDirectoryAsync(string destinationDirectoryName,
169+
public Task ExtractToDirectoryAsync(string destinationDirectoryName,
170170
CancellationToken cancellationToken = default)
171171
{
172172
if (destinationDirectoryName == null)
173173
{
174174
throw new ArgumentNullException(nameof(destinationDirectoryName));
175175
}
176176

177-
await Execute.WhenRealFileSystemAsync(FileSystem,
178-
async () => await _instance.ExtractToDirectoryAsync(destinationDirectoryName,
179-
cancellationToken),
180-
() =>
181-
{
182-
foreach (IZipArchiveEntry entry in Entries)
177+
return ExtractToDirectoryImplAsync(destinationDirectoryName, cancellationToken);
178+
179+
async Task ExtractToDirectoryImplAsync(string d, CancellationToken c)
180+
{
181+
await Execute.WhenRealFileSystemAsync(FileSystem,
182+
async () => await _instance.ExtractToDirectoryAsync(d, c),
183+
() =>
183184
{
184-
entry.ExtractRelativeToDirectory(destinationDirectoryName, overwrite: false);
185-
}
186-
});
185+
foreach (IZipArchiveEntry entry in Entries)
186+
{
187+
entry.ExtractRelativeToDirectory(d, overwrite: false);
188+
}
189+
});
190+
}
187191
}
188192
#endif
189193

190194
#if FEATURE_COMPRESSION_ASYNC
191195
/// <inheritdoc cref="IZipArchive.ExtractToDirectoryAsync(string, bool, CancellationToken)" />
192-
public async Task ExtractToDirectoryAsync(string destinationDirectoryName,
196+
public Task ExtractToDirectoryAsync(string destinationDirectoryName,
193197
bool overwriteFiles,
194198
CancellationToken cancellationToken = default)
195199
{
@@ -198,17 +202,20 @@ public async Task ExtractToDirectoryAsync(string destinationDirectoryName,
198202
throw new ArgumentNullException(nameof(destinationDirectoryName));
199203
}
200204

201-
await Execute.WhenRealFileSystemAsync(FileSystem,
202-
async () => await _instance.ExtractToDirectoryAsync(destinationDirectoryName,
203-
overwriteFiles, cancellationToken),
204-
() =>
205-
{
206-
foreach (IZipArchiveEntry entry in Entries)
205+
return ExtractToDirectoryImplAsync(destinationDirectoryName, overwriteFiles, cancellationToken);
206+
207+
async Task ExtractToDirectoryImplAsync(string d, bool o, CancellationToken c)
208+
{
209+
await Execute.WhenRealFileSystemAsync(FileSystem,
210+
async () => await _instance.ExtractToDirectoryAsync(d, o, c),
211+
() =>
207212
{
208-
entry.ExtractRelativeToDirectory(destinationDirectoryName,
209-
overwrite: overwriteFiles);
210-
}
211-
});
213+
foreach (IZipArchiveEntry entry in Entries)
214+
{
215+
entry.ExtractRelativeToDirectory(d, overwrite: o);
216+
}
217+
});
218+
}
212219
}
213220
#endif
214221

0 commit comments

Comments
 (0)