rspec/rules/S3168/csharp/rule.adoc
Fred Tingaud 16f6c0aecf
Inline adoc when include has no additional value (#1940)
Inline adoc files when they are included exactly once.

Also fix language tags because this inlining gives us better information
on what language the code is written in.
2023-05-25 14:18:12 +02:00

106 lines
3.1 KiB
Plaintext

== Why is this an issue?
An ``++async++`` method with a ``++void++`` return type is a "fire and forget" method best reserved for event handlers because there's no way to wait for the method's execution to complete and respond accordingly. There's also no way to ``++catch++`` exceptions thrown from the method.
Having an ``++async void++`` method that is not an event handler could mean your program works some times and not others because of timing issues. Instead, ``++async++`` methods should return ``++Task++``.
This rule raises an issue when non-event handler methods are both ``++async++`` and ``++void++``.
=== Noncompliant code example
[source,csharp]
----
class HttpPrinter
{
private string content;
public async void CallNetwork(string url) //Noncompliant
{
var client = new HttpClient();
var response = await client.GetAsync(url);
content = await response.Content.ReadAsStringAsync();
}
public async Task PrintContent(string url) // works correctly if web request finishes in under 1 second, otherwise content will be null
{
CallNetwork(url);
await Task.Delay(1000);
Console.Write(content);
}
}
----
=== Compliant solution
[source,csharp]
----
class HttpPrinter
{
private string content;
public async Task CallNetwork(string url)
{
var client = new HttpClient();
var response = await client.GetAsync(url);
content = await response.Content.ReadAsStringAsync();
}
public async Task PrintContent(string url)
{
await CallNetwork(url); // <----- call changed here. If await is not added warning CS4014 will be triggered
await Task.Delay(1000);
Console.Write(content);
}
}
----
=== Exceptions
Event handlers, i.e. methods with two arguments, first one matching type ``++object++`` or name ``++sender++`` and the second being or inheriting from ``++EventArgs++``, are ignored.
Methods named as ``++OnSomething++`` are also ignored.
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Return "Task" instead.
'''
== Comments And Links
(visible only on this page)
=== on 30 Jun 2015, 13:36:13 Ann Campbell wrote:
\[~tamas.vajk] I don't understand the code snippets. The ``++async Task++`` method doesn't return anything.
Also, could you morph the Noncompliant Example into a Compliant Solution, please?
=== on 1 Jul 2015, 07:10:48 Tamas Vajk wrote:
\[~ann.campbell.2] I added the compliant solution.
A method with ``++async++`` keyword returning a ``++Task++`` is like a non ``++async++`` method with ``++void++`` return type. Similarly in an ``++async Task<int>++`` method we can return a simple ``++int++``. (\https://msdn.microsoft.com/en-us/library/hh524395.aspx)
=== on 1 Jul 2015, 11:31:53 Ann Campbell wrote:
\[~tamas.vajk] that makes me wonder if we should generalize this rule to catch _any_ ``++async++`` method that does not return a ``++Task++``...?
=== on 1 Jul 2015, 11:49:54 Tamas Vajk wrote:
\[~ann.campbell.2] That's a compiler error (CS1983, _The return type of async must be void, Task or Task<T>_).
=== on 1 Jul 2015, 11:59:39 Ann Campbell wrote:
Okay, thanks [~tamas.vajk]
endif::env-github,rspecator-view[]