dotnet/roslyn

Better codegen for conditional-access + pattern checks.

Open

#69.411 aperta il 5 ago 2023

Vedi su GitHub
 (7 commenti) (5 reazioni) (0 assegnatari)C# (4257 fork)batch import
Area-CompilersCode Gen Qualityhelp wanted

Metriche repository

Star
 (20.414 star)
Metriche merge PR
 (Merge medio 6g 17h) (256 PR mergiate in 30 g)

Descrizione

Given code like the following:

    static void Main(string[] args)
    {
        if (args?.Length is 1)
            Console.WriteLine(true);
    }

The compiler currently compiles that similarly to the following:

int? __t1 = __argsTemp?.Length;
if (__t1.HasValue && __t1.GetValueOrDefault() == 1) ...

While correct, this appears to be unnecessarily expensive. Specifically, because the pattern itself does not have null in its acceptance-set, there's no need to actually produce and instantiate a nullable-int on the stack just to test that instead. Rather, the above would be better compiled to something similar to:

if (__argsTemp != null && __argsTemp.Length is 1)

In other words, once the null check is performed, if it is null, then the value of args?.Length would be known to be null, which could never match 1, so no further checks are necessary. However, if the null check is performed and the value is not null, then it is known that it is safe to access members of it directly. This avoids unnecessary nullable allocations on the stack in either case.

Note: this could also be done for operators like == and != on primitive types, when the comparands are constants.

Guida contributor