Parameter name passed as a string literal instead of NameOf

ID

vbnet.maintainability.use_nameof

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Api Design

Language

VB.NET

Description

Reports argument-validation exceptions - ArgumentNullException, ArgumentException and ArgumentOutOfRangeException - constructed with a hard-coded string literal in the paramName position, where the NameOf operator should be used instead.

Rationale

A string literal parameter name is not checked by the compiler and is not updated by a rename. When the parameter is renamed - by hand or by a refactoring tool - the literal keeps the old name, so the exception blames a parameter that no longer exists and the message reaching the caller, the log and the bug report is wrong. A typo in the literal has the same effect and is never reported. NameOf is resolved at compile time, so a stale or misspelled name becomes a compilation error rather than a misleading run-time message, and it costs nothing at run time because the compiler emits the same constant string.

The following code illustrates the pattern detected by this rule:

Public Sub Register(ByVal userName As String, ByVal age As Integer)
    ' FLAGGED: Parameter name passed as a string literal instead of NameOf
    If userName Is Nothing Then Throw New ArgumentNullException("userName")
    ' FLAGGED: Parameter name passed as a string literal instead of NameOf
    If age < 0 Then Throw New ArgumentOutOfRangeException("age", "Age cannot be negative.")
End Sub

Remediation

Replace the literal with NameOf(parameter). Note the argument order differs between the exception types: ArgumentNullException and ArgumentOutOfRangeException take paramName first, while ArgumentException takes the message first and paramName second.

' Before: the literal survives a rename of the parameter
If userName Is Nothing Then Throw New ArgumentNullException("userName")
If age < 0 Then Throw New ArgumentOutOfRangeException("age", "Age cannot be negative.")

' After: the compiler keeps the name in step
If userName Is Nothing Then Throw New ArgumentNullException(NameOf(userName))
If age < 0 Then Throw New ArgumentOutOfRangeException(NameOf(age), "Age cannot be negative.")

Configuration

This detector does not need any configuration.