mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Three places decided independently whether a backing field would still be declared, and they disagreed. ReplaceBackingFieldUsage rewrote a constructor store into a property assignment whenever the property looked collapsible, without asking whether PatternStatementTransform would actually remove the declaration; ConvertField printed the "field" keyword on the FieldKeyword setting alone, ignoring the GetterOnlyAutomaticProperties veto that MemberIsHidden applies to the same field. Two consequences, both silent. A setter-less property under GetterOnlyAutomaticProperties = false kept its declaration and got "field" in the getter anyway, so the keyword bound to a second synthesized field and the declared one went unwritten. A settable property under AutomaticProperties = false had its initializing store turned into a property assignment that TransformFieldAndConstructorInitializers could no longer lift, leaving the constructor in the output with an unconverted base-constructor call. BackingFieldWillBeRemoved is now the single verdict every branch consults, and it mirrors the transform's own entry gate. A property that keeps explicit accessors is no longer addressed by name: the store stays a field reference and becomes the property initializer, which is what field-backed storage means. The one exception is a setter-less property's constructor store, which C# allows to be written as an assignment and which has no other expressible form. IsBackingFieldOfAutomaticProperty now answers through TryGetBackingField instead of its own name check, so the two directions of "is this field that property's storage" cannot diverge on staticness or field type. ReplaceBackingFieldUsage dispatches on the resolve result rather than the identifier's spelling; after ConvertField the same field appears both as "field" and under its metadata name carrying the same annotation, so matching the name was matching the wrong thing. The keyword's own precondition moves into a CanUseFieldKeyword local function. Seven clauses with comment blocks wedged between them had to be read as one expression; as one early return per rule the list reads in order. Assisted-by: Claude:claude-opus-5[1m]:Claude Code