52 lines
1.7 KiB
Plaintext
52 lines
1.7 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Because of the way ``++async/await++`` methods are rewritten by the compiler, any exceptions thrown during the parameters check will happen only when the task is observed. That could happen far away from the source of the buggy code or never happen for fire-and-forget tasks.
|
|
|
|
|
|
Therefore it is recommended to split the method into two: an outer method handling the parameter checks (without being ``++async/await++``) and an inner method to handle the iterator block with the ``++async/await++`` pattern.
|
|
|
|
|
|
This rule raises an issue when an ``++async++`` method throws any exception derived from ``++ArgumentException++`` and contains ``++await++`` keyword.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,text]
|
|
----
|
|
public static async Task SkipLinesAsync(this TextReader reader, int linesToSkip) // Noncompliant
|
|
{
|
|
if (reader == null) { throw new ArgumentNullException(nameof(reader)); }
|
|
if (linesToSkip < 0) { throw new ArgumentOutOfRangeException(nameof(linesToSkip)); }
|
|
|
|
for (var i = 0; i < linesToSkip; ++i)
|
|
{
|
|
var line = await reader.ReadLineAsync().ConfigureAwait(false);
|
|
if (line == null) { break; }
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,text]
|
|
----
|
|
public static Task SkipLinesAsync(this TextReader reader, int linesToSkip)
|
|
{
|
|
if (reader == null) { throw new ArgumentNullException(nameof(reader)); }
|
|
if (linesToSkip < 0) { throw new ArgumentOutOfRangeException(nameof(linesToSkip)); }
|
|
|
|
return reader.SkipLinesInternalAsync(linesToSkip);
|
|
}
|
|
|
|
private static async Task SkipLinesInternalAsync(this TextReader reader, int linesToSkip)
|
|
{
|
|
for (var i = 0; i < linesToSkip; ++i)
|
|
{
|
|
var line = await reader.ReadLineAsync().ConfigureAwait(false);
|
|
if (line == null) { break; }
|
|
}
|
|
}
|
|
----
|
|
|