Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Download Microsoft EdgeMore info about Internet Explorer and Microsoft Edge
Table of contentsExit focus mode

Operator overloading - predefined unary, arithmetic, equality, and comparison operators

  • 2025-06-13
Feedback

In this article

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:

  • It includes apublic modifier.
  • A unary operator has one input parameter. A binary operator has two input parameters. In each case, at least one parameter must have typeT orT? whereT is the type that contains the operator declaration.
  • It includes thestatic modifier, except for the compound assignment operators, such as+=.
  • The increment (++) 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.

Overloadable operators

The following table shows the operators that can be overloaded:

OperatorsNotes
+x,-x,!x,~x,++,--,true,falseThetrue 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 >= yMust 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:

  • It must include thepublic modifier.
  • It can't include thestatic modifier.
  • The return type must bevoid.
  • The declaration must include one parameter, which represents the right hand side of the compound assignment.

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:

  • It must include thepublic modifier.
  • It can't include thestatic modifier.
  • The return type must bevoid.
  • It can't declare any parameters, even if those parameters have a default value.

Non overloadable operators

The following table shows the operators that can't be overloaded:

OperatorsAlternatives
x && y,x || yOverload both thetrue andfalse operators and the& or| operators. For more information, seeUser-defined conditional logical operators.
a[i],a?[i]Define anindexer.
(T)xDefine 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.

Operator overload resolution

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 ofxbefore 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.

C# language specification

For more information, see the following sections of theC# language specification:

See also

Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, seeour contributor guide.

Feedback

Was this page helpful?

YesNo

In this article

Was this page helpful?

YesNo