#4136·ILSpy

Lifted null comparison decompiles to HasValue/GetValueOrDefault with a '? true : false'

Author: siegfriedpammerCreated Sep 13, 2026Updated Sep 16, 2026
LabelsDecompilerOutput

Input code

SixLabors.ImageSharp 4.1.1, SixLabors.ImageSharp.Formats.Png.PngEncoderCore.WriteXmpChunk (and WriteExifChunk, same shape):

bash
ilspycmd ~/.cache/nugetfuzz/sixlabors.imagesharp/4.1.1/lib/net8.0/SixLabors.ImageSharp.dll \
    -t SixLabors.ImageSharp.Formats.Png.PngEncoderCore

Erroneous output

Current master (dbf23c6e4):

csharp
byte[] data = meta.XmpProfile.Data;
int? num = data?.Length;
if ((num ?? 0) == 0)
{
    return;
}

With #4091 (6fcb387ff) the lifted comparison is expanded and wrapped in a no-op conditional:

csharp
byte[] data = meta.XmpProfile.Data;
int? num = data?.Length;
if ((!num.HasValue || num.GetValueOrDefault() == 0) ? true : false)
{
    return;
}

Two separate things happen here: the ?? form is lost, and the resulting bool expression gains a ? true : false.

Other instances from the same corpus run (top-200 nuget.org packages, #4091 against its merge base):

  • Swashbuckle.AspNetCore.SwaggerGen 10.2.3, XmlCommentsRequestBodyFilter: if ((num2 ?? 1) == 0 || num == 0) becomes if ((num2.HasValue && num2.GetValueOrDefault() == 0) || num == 0)
  • OpenTelemetry.Exporter.OpenTelemetryProtocol serializer: ((statusCode ?? StatusCode.Unset) != StatusCode.Unset) becomes (statusCode.HasValue && statusCode.GetValueOrDefault() != StatusCode.Unset)

Details

  • Product in use: ICSharpCode.Decompiler, built from source
  • Version in use: not reproducible on master (dbf23c6e4); measured at 6fcb387ff against merge base 712ad1aed. Three types in the corpus are affected; the output remains correct.

Filed by an AI agent (Claude) on Siegfried's behalf.