Skip to main content
The - operator in C# functions as both a unary operator for numeric negation and a binary operator for arithmetic subtraction, enumeration subtraction, delegate removal, and pointer arithmetic. Its behavior, return type, and overflow mechanics are resolved at compile-time based on the arity of the operation, the static types of its operands, and the evaluation context.

Unary Negation

When applied to a single operand, the - operator computes the numeric negation of that operand, effectively subtracting the operand from zero.
  • Supported Types: Predefined for int, long, float, double, and decimal.
  • Type Mechanics: When the unary - operator is applied to a uint, the operand is implicitly promoted to a long, and the operation returns a long. The operator is not defined for ulong; attempting to apply it to a ulong results in a compile-time error (CS0023).
  • Overflow Mechanics: The two’s complement representation of integers means the absolute value of int.MinValue and long.MinValue exceeds the maximum positive value of their respective types. Applying the unary - to these minimum values in an unchecked context results in a wrap-around, returning the minimum value itself. In a checked context, this operation throws a System.OverflowException.

Binary Subtraction

When applied to two operands, the - operator computes the arithmetic difference between the left operand (minuend) and the right operand (subtrahend).
  • Supported Types: Predefined for all standard numeric types (int, uint, long, ulong, float, double, decimal).
  • Type Mechanics: If the operands are of different types, C# applies implicit numeric promotions to convert them to a common type before performing the subtraction. The return type matches this promoted type.
  • Overflow Mechanics: For integral types, if the mathematical difference cannot be represented within the bounds of the return type, an arithmetic overflow occurs. In an unchecked context, the high-order bits are discarded, resulting in a wrap-around. In a checked context, the operation throws a System.OverflowException. Floating-point subtraction (float, double) never throws an overflow exception; instead, it yields positive or negative infinity.

Lifted Operators for Nullable Types

For nullable value types (T?), C# automatically provides lifted versions of the predefined unary and binary - operators. The lifted operator evaluates the HasValue property of its operands. If either or both operands evaluate to null, the result of the operation is null. Otherwise, the operator unwraps the underlying values, applies the standard - operator, and wraps the result back into a nullable type.

DateTime and TimeSpan Subtraction

C# provides predefined binary - operators for the System.DateTime, System.DateTimeOffset, and System.TimeSpan structs to handle chronological arithmetic:
  1. DateTime and DateTime: Subtracting a DateTime from another DateTime yields a System.TimeSpan representing the duration between the two points in time.
  2. DateTime and TimeSpan: Subtracting a TimeSpan from a DateTime yields a new DateTime decremented by the specified duration.
  3. TimeSpan and TimeSpan: Subtracting a TimeSpan from another TimeSpan yields a new TimeSpan representing the difference between the two durations.

Enumeration Subtraction

C# provides predefined binary - operators for all enum types, supporting two distinct operations:
  1. Enum and Enum: Subtracting two enum values of the same type yields the difference between their underlying numeric values. The return type is the underlying integral type of the enumeration.
  2. Enum and Integer: Subtracting an integer from an enum value yields a new enum value decremented by the integer amount. The return type is the enumeration type itself.

Delegate Removal

For operands of concrete delegate types (such as System.Action, System.Func<T>, or custom delegate signatures), the binary - operator performs delegate removal. It evaluates the invocation lists of both operands. The operator is not defined on the System.Delegate base class itself; attempting to use it on variables typed strictly as System.Delegate results in a compile-time error (CS0019).
  • Mechanics: If the right operand’s invocation list is a contiguous sublist of the left operand’s invocation list, the operator returns a new delegate with that sublist removed. If the right operand’s invocation list matches multiple sublists within the left operand’s invocation list, the - operator removes only the last matching contiguous sublist. If the right operand is not found, or if the right operand is null, it returns the left operand unchanged. If the removal results in an empty invocation list, the operator returns null.

Pointer Arithmetic

In an unsafe context, the binary - operator supports pointer arithmetic with two distinct signatures:
  1. Pointer and Integer: Subtracting an integer offset from a pointer returns a new pointer of the same type, decremented by the offset multiplied by the size of the pointer’s underlying type.
  2. Pointer and Pointer: Subtracting a pointer from another pointer of the same type returns a long representing the distance (in elements, not bytes) between the two memory addresses.

Operator Overloading

User-defined types (struct or class) can overload the - operator to define custom negation or subtraction logic. Overloads must be declared as public static. If a type overloads the binary - operator, it does not automatically overload the -= compound assignment operator; however, C# automatically evaluates x -= y as x = x - y using the overloaded binary operator.
Tired of Poor C# Skills? Fix That With Deep Grasping!Learn More