Constructorargument Param Exists
ID |
csharp.constructorargument_param_exists |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
CSharp |
Tags |
api-design, code_smell, markup-extension, string-wiring |
Description
Reports a property carrying [ConstructorArgument("name")] where name matches no parameter of any
constructor of the declaring class. The attribute pairs a property with a constructor parameter so
that markup-extension tooling can round-trip the extension back to its positional form; the pairing
is made by string, so nothing checks it at compile time.
Rationale
[ConstructorArgument] tells a designer or serializer that this property holds the value that was
passed as that constructor argument. With a correct name, the extension can be written back as
{Lookup someKey}; with a wrong one, the property is simply not recognised as corresponding to any
argument and the value does not make it back out.
Nothing throws. The build is clean, the extension still works when constructed from markup, and only the round trip is broken — so a typo, a renamed parameter or a capitalization slip can survive a long time before anyone notices a serialized form that has lost a value. Matching is case-sensitive, which is where most of these come from.
public class LookupExtension : MarkupExtension
{
public LookupExtension(string key)
{
Key = key;
}
[ConstructorArgument("keyName")] // FLAW — the parameter is named key
public string Key { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) => Key;
}
public class RangeExtension : MarkupExtension
{
public RangeExtension(int low, int high)
{
Low = low;
High = high;
}
[ConstructorArgument("low")] // OK — matches a parameter exactly
public int Low { get; set; }
[ConstructorArgument("High")] // FLAW — the parameter is named high, lowercase
public int High { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) => Low;
}
Parameters of every constructor are considered, so a property matching an overload’s parameter is not reported. A class that declares no instance constructor at all is left alone: there is nothing for the name to match, and the missing constructor is the real problem. So is an argument that is not a string literal, whose value the rule cannot read.
Remediation
Correct the string to the exact name of the constructor parameter the property carries, including its casing. If the parameter was renamed, rename it back or update every attribute that refers to it. If the property does not correspond to a constructor argument at all, remove the attribute.