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.