Use Nameof

ID

csharp.use_nameof

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

CSharp

Tags

code_smell, exception, maintainability, refactoring

Description

Reports a string literal inside a throw that writes out the name of a parameter in scope — either as the whole literal, or spelled out inside a message — where nameof(parameter) should be used instead.

Rationale

A parameter name spelled out as text is invisible to the compiler and to every rename tool. Once someone renames the parameter, the literal keeps the old spelling: the exception then blames a parameter that no longer exists, and the developer reading the stack trace looks for something that is not in the signature.

nameof(parameter) produces the same string at compile time while staying attached to the declaration, so a rename updates it and a typo becomes a compile error rather than a misleading message at run time.

A message that spells the parameter out reads just as wrongly after a rename as the argument-name position does, so it is reported too. That case needs a guard against accidental matches: a short name turns up inside ordinary words — id inside identifier, path inside pathway — so a name that is only contained in the literal is reported from five characters upwards. A whole-literal match is reported at any length. The check stays limited to literals inside a throw.

Interpolated messages such as $"{documentPath} is unreadable" are already rename-safe and are not reported.

using System;

public class Range
{
    public void Check(int count, string id)
    {
        if (id == null)
        {
            throw new ArgumentNullException("id");              // FLAW — a rename leaves this behind
        }

        if (count < 0)
        {
            throw new ArgumentException("must be positive", "count"); // FLAW — same for the argument name
        }
    }

    public void Open(string documentPath, string path)
    {
        if (documentPath == null)
        {
            throw new ArgumentException("documentPath must be provided"); // FLAW — the message names it
        }

        if (path == null)
        {
            throw new ArgumentException("the pathway is unknown");   // OK, under five characters
        }
    }

    public void CheckOk(string id)
    {
        if (id == null)
        {
            throw new ArgumentNullException(nameof(id));         // OK, follows the rename
        }
    }
}

Remediation

Replace the literal with nameof(parameter). Where the parameter is named inside a message, keep the prose and interpolate the name, as in $"{nameof(count)} must be positive", so the sentence follows a rename as well as the argument-name position does.