Covariant Array Conversion
ID |
csharp.covariant_array_conversion |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
CSharp |
Tags |
reliability, suspicious-comparison |
Description
Reports local declarations of the form object[] x = stringArr; (or any
Base[] x = derivedArr;) where the declared element type is a strict supertype
of the runtime element type. C# arrays are covariant, so the assignment compiles,
but a later x[i] = somethingElse; whose value is assignable to Base but not
to the runtime element type throws ArrayTypeMismatchException.
Rationale
Array covariance is a long-standing source of surprising runtime failures in C#.
A string[] is an object[] at compile time, but the CLR remembers the
runtime element type and rejects writes that do not fit it. The check is
conservative on purpose: it only flags the canonical bug shape (object[]
declared, derived-array initializer), in which the only safe operations are
reads.
string[] names = { "a", "b" };
object[] xs = names; // FLAW — covariant conversion
xs[0] = 42; // throws ArrayTypeMismatchException
object[] safe = new object[] { 1, "two" }; // OK — homogeneous object[]
string[] same = names; // OK — same element type
Remediation
Use the actual element type for the declared variable (string[]), or use a
read-only abstraction like IReadOnlyList<object> to make the intent of "this
is for reading only" explicit. For a heterogeneous container, build a fresh
object[] rather than aliasing an existing derived array.