This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
A user-defined type can overload a predefined C# operator. That is, a type can provide the custom implementation of an operation in case one or both of the operands are of that type. TheOverloadable operators section shows which C# operators can be overloaded.
Use theoperator
keyword to declare an operator. An operator declaration must satisfy the following rules:
public
modifier.T
orT?
whereT
is the type that contains the operator declaration.static
modifier, except for the compound assignment operators, such as+=
.++
) and decrement (--
) operators can be implemented as either static or instance methods.The following example defines a simplified structure to represent a rational number. The structure overloads some of thearithmetic operators:
public struct Fraction{ private int numerator; private int denominator; public Fraction(int numerator, int denominator) { if (denominator == 0) { throw new ArgumentException("Denominator cannot be zero.", nameof(denominator)); } this.numerator = numerator; this.denominator = denominator; } public static Fraction operator +(Fraction operand) => operand; public static Fraction operator -(Fraction operand) => new Fraction(-operand.numerator, operand.denominator); public static Fraction operator +(Fraction left, Fraction right) => new Fraction(left.numerator * right.denominator + right.numerator * left.denominator, left.denominator * right.denominator); public static Fraction operator -(Fraction left, Fraction right) => left + (-right); public static Fraction operator *(Fraction left, Fraction right) => new Fraction(left.numerator * right.numerator, left.denominator * right.denominator); public static Fraction operator /(Fraction left, Fraction right) { if (right.numerator == 0) { throw new DivideByZeroException(); } return new Fraction(left.numerator * right.denominator, left.denominator * right.numerator); } // Define increment and decrement to add 1/den, rather than 1/1. public static Fraction operator ++(Fraction operand) => new Fraction(operand.numerator++, operand.denominator); public static Fraction operator --(Fraction operand) => new Fraction(operand.numerator--, operand.denominator); public override string ToString() => $"{numerator} / {denominator}"; // New operators allowed in C# 14: public void operator +=(Fraction operand) => (numerator, denominator ) = ( numerator * operand.denominator + operand.numerator * denominator, denominator * operand.denominator ); public void operator -=(Fraction operand) => (numerator, denominator) = ( numerator * operand.denominator - operand.numerator * denominator, denominator * operand.denominator ); public void operator *=(Fraction operand) => (numerator, denominator) = ( numerator * operand.numerator, denominator * operand.denominator ); public void operator /=(Fraction operand) { if (operand.numerator == 0) { throw new DivideByZeroException(); } (numerator, denominator) = ( numerator * operand.denominator, denominator * operand.numerator ); } public void operator ++() => numerator++; public void operator --() => numerator--;}public static class OperatorOverloading{ public static void Main() { var a = new Fraction(5, 4); var b = new Fraction(1, 2); Console.WriteLine(-a); // output: -5 / 4 Console.WriteLine(a + b); // output: 14 / 8 Console.WriteLine(a - b); // output: 6 / 8 Console.WriteLine(a * b); // output: 5 / 8 Console.WriteLine(a / b); // output: 10 / 4 }}
You could extend the preceding example bydefining an implicit conversion fromint
toFraction
. Then, overloaded operators would support arguments of those two types. That is, it would become possible to add an integer to a fraction and obtain a fraction as a result.
You also use theoperator
keyword to define a custom type conversion. For more information, seeUser-defined conversion operators.
The following table shows the operators that can be overloaded:
Operators | Notes |
---|---|
+x ,-x ,!x ,~x ,++ ,-- ,true ,false | Thetrue andfalse operators must be overloaded together. |
x + y ,x - y ,x * y ,x / y ,x % y ,x & y ,x | y ,x ^ y ,x << y ,x >> y ,x >>> y | |
x == y ,x != y ,x < y ,x > y ,x <= y ,x >= y | Must be overloaded in pairs as follows:== and!= ,< and> ,<= and>= . |
+= ,-= ,*= ,/= ,%= ,&= ,\|= ,^= ,<<= ,>>= ,>>>= | The compound assignment operators can be overloaded in C# 14 and later. |
A compound assignment overloaded operator must follow these rules:
public
modifier.static
modifier.void
.Beginning with C# 14, the increment (++
) and decrement (--
) operators can be overloaded as instance members. Instance operators can improve performance by avoiding the creation of a new instance. An instance operator must follow these rules:
public
modifier.static
modifier.void
.The following table shows the operators that can't be overloaded:
Operators | Alternatives |
---|---|
x && y ,x || y | Overload both thetrue andfalse operators and the& or| operators. For more information, seeUser-defined conditional logical operators. |
a[i] ,a?[i] | Define anindexer. |
(T)x | Define custom type conversions performed by a cast expression. For more information, seeUser-defined conversion operators. |
^x ,x = y ,x.y ,x?.y ,c ? t : f ,x ?? y ,??= y ,x..y ,x->y ,=> ,f(x) ,as ,await ,checked ,unchecked ,default ,delegate ,is ,nameof ,new ,sizeof ,stackalloc ,switch ,typeof ,with | None. |
Before C# 14, the compound operators can't be overloaded. Overloading the corresponding binary operator implicitly overloads the corresponding compound assignment operator.
Important
This section applies to C# 14 and later. Before C# 14, user-defined compound assignment operators and instance increment and decrement operators aren't allowed.
Ifx
is classified as a variable in a compound assignment expression such asx «op»= y
, instance operators are preferred over any static operator for«op»
. If an overloaded«op»=
operator isn't declared for the type ofx
orx
isn't classified as a variable, the static operators are used.
For the postfix operator++
, ifx
isn't classified as a variableor the expressionx++
is used, the instanceoperator++
is ignored. Otherwise, preference is given to the instanceoperator ++
. For example,
x++; // Instance operator++ preferred.y = x++; // instance operator++ isn't considered.
The reason for this rule is thaty
should be assigned to the value ofx
before it's incremented. The compiler can't determine that for a user-defined implementation in a reference type.
For the prefix operator++
, ifx
is classified as a variable in++x
, the instance operator is preferred over a static unary operator.
For more information, see the following sections of theC# language specification:
Was this page helpful?
Was this page helpful?