Do Not Expose Generic Lists

ID

csharp.do_not_expose_generic_lists

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Best Practice

Language

CSharp

Tags

api_design, best_practice

Description

Reports public or protected API members whose declared type is System.Collections.Generic.List<T>. The .NET design guidelines recommend exposing an interface instead, so callers depend on the contract rather than the specific implementation.

Rationale

Returning a concrete List<T> leaks the implementation. Callers can mutate the collection, the implementation cannot later swap to a different backing structure (immutable list, array segment, lazy view) without a breaking change, and read-only intent cannot be communicated. IList<T>, ICollection<T> and IReadOnlyList<T> model the relevant contracts directly.

public class Inventory
{
    public List<string> Items { get; }                            // FLAW

    public List<string> Fetch(int n) => new();                    // FLAW

    public IReadOnlyList<string> History { get; } = new List<string>(); // OK
    public IList<string> Categories { get; }                      // OK

    public IList<string> Search(string term) => new List<string>(); // OK
}

Remediation

Change the declared return type or property type to the most appropriate collection interface — IReadOnlyList<T> for read-only consumers, IList<T> or ICollection<T> when mutation is part of the contract.