Operator overload has no named alternate method
ID |
vbnet.maintainability.operator_overloads_have_named_alternates |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Api Design |
Language |
VB.NET |
Description
Reports an overloaded operator whose declaring type does not also expose the named method that the .NET design guidelines pair with that operator - Add for +, Subtract or Negate for -, Multiply for *, Divide for /, Concatenate for &, BitwiseAnd for And, BitwiseOr for Or and LogicalNot for Not. A type that declares both the operator and its named method is not reported, in either declaration order.
Rationale
Operator overloading is an optional language feature, so an operator alone does not make the behaviour reachable from every .NET language that may consume the assembly. A caller in a language without operator overloading, and any caller working through reflection, late binding, an expression tree or a dynamically generated call, has no way to invoke op_Addition other than by name - and that name is a compiler-generated detail, not part of a documented API. The named alternate is also what appears in IntelliSense and in generated API documentation, so without it the capability is effectively invisible to anyone browsing the type.
The following code illustrates the pattern detected by this rule:
Public Currency As String
' FLAGGED: Operator overload has no named alternate method
Public Shared Operator +(ByVal a As Money, ByVal b As Money) As Money
Return New Money With {.Amount = a.Amount + b.Amount, .Currency = a.Currency}
End Operator
' FLAGGED: Operator overload has no named alternate method
Public Shared Operator -(ByVal a As Money, ByVal b As Money) As Money
Return New Money With {.Amount = a.Amount - b.Amount, .Currency = a.Currency}
End Operator
' FLAGGED: Operator overload has no named alternate method
Public Shared Operator *(ByVal a As Money, ByVal factor As Decimal) As Money
Return New Money With {.Amount = a.Amount * factor, .Currency = a.Currency}
End Operator
' FLAGGED: Operator overload has no named alternate method
Public Shared Operator /(ByVal a As Money, ByVal divisor As Decimal) As Money
Return New Money With {.Amount = a.Amount / divisor, .Currency = a.Currency}
End Operator
End Structure
Public Class Vector3
Public Shared Function Multiply(ByVal a As Vector3, ByVal k As Double) As Vector3
Return a
Remediation
Add a Public Shared Function with the guideline name for the operator, and have the operator delegate to it so the two can never drift apart. For example, keep the arithmetic in Public Shared Function Add(a As Money, b As Money) As Money and reduce the operator body to Return Add(a, b). Use Negate for the unary minus and Subtract for the binary one.