Skip to content

Parameterless struct initialization re-uses values #57870

@jaredpar

Description

@jaredpar

Simplified repro from original issue:

using System;

var x = new S3Options { BasePath = "p/a/t/h", Bucket = "root" };
var y = new S3Options { BasePath = "p/a/t/h" };

Console.WriteLine(y.Bucket);

public record struct S3Options
{
    public string? Bucket { get; init; }
    public string? BasePath { get; init; } = "value";
}

This prints out root where it should print out nothing. The reason this is happening is that we are re-using a local for initialization purposes. This is a practice we've had since probably C# 1.0. Prior to C# 10 though we cleared out the local between uses via .initobj instruction. In C# 10 though when there is a parameterless struct ctor, explicit or implicit because of initializers, we call the .ctor on the struct instead.

IL without paramterless ctor

        IL_0024: ldloca.s 2
        IL_0026: initobj S3Options
        IL_002c: ldloca.s 2
        IL_002e: ldstr "p/a/t/h"

IL with parameterless ctor

        IL_0023: ldloca.s 2
        IL_0025: call instance void S3Options::.ctor()
        IL_002a: ldloca.s 2
        IL_002c: ldstr "p/a/t/h"

The .ctor call though does not clear out all of the existing values, it just sets the minimal necessary set. Because Bucket doesn't have an explicit initializer it ends up re-using the previous value.

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions