Input code
The following compiles fine (Release), but the chained constructor call is not reconstructed when decompiled. The failing member is the CtorChild(string) constructor.
using System;
public class CtorBase
{
public CtorBase(int a, int b, int c, string s) { }
}
public sealed class CtorChild : CtorBase
{
public string Value;
public CtorChild(string value)
: base(0, value?.Length ?? throw new ArgumentNullException(nameof(value)), value.Length, nameof(value))
{
Value = value;
}
}
Erroneous output
public CtorChild(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
base..ctor(0, value.Length, value.Length, "value");
Value = value;
}
base..ctor(...) is not valid C# (a parse error: base. followed by .ctor), so the output does not compile. The same happens with a : this(...) chain (emitted as this..ctor(...)).
Expected output:
public CtorChild(string value)
: base(0, value?.Length ?? throw new ArgumentNullException("value"), value.Length, "value")
{
Value = value;
}
Details
Input code
The following compiles fine (Release), but the chained constructor call is not reconstructed when decompiled. The failing member is the
CtorChild(string)constructor.Erroneous output
base..ctor(...)is not valid C# (a parse error:base.followed by.ctor), so the output does not compile. The same happens with a: this(...)chain (emitted asthis..ctor(...)).Expected output:
Details
fe50c00f(11.0.0.9086); also reproduces on 10.1 (10.1.0.8386)IbanNet.Registry.Patterns.PatternToken(string)(net462).TransformFieldAndConstructorInitializers.MoveConstructorInitializerinspects onlyBody.Statements.FirstOrDefault(). When the compiler hoists an argument null-check (here fromvalue?.Length ?? throw ...withvaluereused in a later argument) asif (value == null) throw ...;, that guard becomes the first statement, theThisCallClassPattern/ThisCallStructPatternmatch fails, and the chained call stays in the body. Folding the guard back into the initializer argument (value ?? throw ...) would restore a valid initializer.