Operators overloading. General information. Overloading of unary operators –, !, ++, —
Contents
- 1. The concept of operator overloading
- 2. Requirements and restrictions that are imposed when overloading operators
- 3. List of operators that can and cannot be overloaded
- 4. The general form of operator overloading in a class. The operator keyword
- 5. Features of overloading unary operators
- 6. Example of overloading a unary operator – (minus)
- 7. An example of overloading the unary operator ! (negation)
- 8. Example of overloading unary operators ++, — (increment, decrement)
- 9. Example of overlading unary operator ~ (addition to 1)
- Related topics
Search other resources:
1. The concept of operator overloading
In the C# language, it is possible to set an operator (+, -, != and others) for a specific class or structure, which can be used to perform any action. As a rule, these actions are performed on objects of this class (structure). Representing actions through understandable (natural) statements improves the perception of program code. Thus, the use of well-known operators can be both for basic types (int, double, char and others), and for user-defined classes (user-defined types). The mechanism for specifying standard operators for a given class or structure in order to improve the readability of programs is called operator overloading. Operators can be overloaded for both classes and structures.
Many standard classes implement overloading of many operators. For example, the String class has overloaded operators == and !=, which makes it convenient to compare two strings for equality (inequality).
⇑
2. Requirements and restrictions that are imposed when overloading operators
When performing operator overloading in classes, a number of requirements must be met:
- to implement the overload, you need to use public static methods declared in the class;
- it is forbidden to use the ref or out modifiers in the operator method;
- in an operator method, the type of the parameter or the type of the return value must match the type (class) in which this operator is overloaded.
The following restrictions are also imposed on operator overloading:
- overloading does not change the priority of operators;
- when overloading the operator, the number of operands used cannot be changed;
- not all operators can be overloaded.
⇑
3. List of operators that can and cannot be overloaded
Not all operators allow overloading. The table below lists the operators that can be overloaded.
Operators | Category of operators |
− | Reversal of sign |
! | Logical negation |
~ | Addition to 1 |
++, −− | Increment, decrement |
true, false | Object truth |
+, −, *, /, % | Arithmetic operators |
&&, || | Logical operators |
&, |, ^, <<, >> | Bit operators |
==, !=, <, >, <=, >= | Comparison operators |
[ ] | Array element access operation |
( ) | Cast operations |
The following is a list of operators that cannot be overloaded.
Operators | Category |
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= | Shorthand assignment operators |
= | Assignment |
. | Access to elements |
?: | Ternary conditional operator |
new | Object creation |
as, is, typeof | Get information about type |
->, sizeof, *, & | Accessible in unsafe code |
⇑
4. The general form of operator overloading in a class. The operator keyword
To overload an operator in a class, use the operator keyword with the following syntax.
public static return_type operator op(parameters)
where
- op – the operator to be overloaded (+, –, != etc.);
- return_type – the type that is returned when using the op operator;
- parameters – the list of parameters that the operator receives. For unary operators (-, !, ++, –) parameters contains only 1 parameter, for binary operators – 2 parameters.
⇑
5. Features of overloading unary operators
Unary operators that can be overloaded include the following operators:
- – – unary minus;
- ! – logical negation;
- ++ – increment;
- –– – decrement.
Since all overloaded operators are static methods, they do not receive the this pointer of the current instance. As a consequence, all operator methods that overload unary operators take one parameter. This parameter must be a class type.
In the most general case, the unary operator overload in the ClassName class is as follows
class ClassName { ... public static return_type op(ClassName param) { // Actions performed // ... } }
where
- op – designation of one of the unary operators –, !, ++, ––;
- param – some parameter;
- return_type – the return type. It can be any type used in the program.
After that, the op statement can be used on the class ClassName something like this
value = op Obj;
where
- value – the resulting value of type return_type;
- Obj – an instance of the ClassName class.
For example, if the ++ operator is overloaded, then the call will be
value = ++Obj;
⇑
6. Example of overloading a unary operator – (minus)
The example shows an overload of the unary operator – (minus) using the example of a class that describes a complex number. With the help of an overloaded operator, the signs of the real and imaginary parts of a complex number are reversed.
using System; namespace ConsoleApp6 { class Complex { // Internal fields of the class private double re, im; // Constructor public Complex(double re, double im) { this.re = re; this.im = im; } // Internal field access properties public double Re { get { return re; } set { re = value; } } public double Im { get { return im; } set { im = value; } } // Operator method that overloads the unary operator '-' public static Complex operator-(Complex cm) { return new Complex(-cm.re, -cm.im); } // Method that outputs the state of the current instance public void Print(string msg) { Console.Write(msg + " => "); Console.Write(re); if (im >= 0) Console.Write("+"); Console.WriteLine(im.ToString() + "*j"); } } internal class Program { static void Main(string[] args) { // Create an instance of the Complex class Complex c1 = new Complex(2.4, -3.8); // Get the state of an instance c1.Print("c1"); // c1 => 2.4-3.8*j // Create a reference to Complex class Complex c2; // Assign to reference the return result from the overloaded operator - c2 = -c1; // Complex::operator-(c1); // Print the state of the instance c2 c2.Print("c2"); // c2 => -2.4+3.8*j Console.ReadKey(); } } }
Result
c1 => 2.4-3.8*j c2 => -2.4+3.8*j
⇑
7. An example of overloading the unary operator ! (negation)
On the example of a class that describes a triangle along its sides, an overload of the unary operator ! is implemented. The operator method returns true if the triangle is equilateral within the specified precision. Otherwise, false is returned.
The example demonstrates only a minimal set of methods for the purpose of demonstrating the overload of the ! (negation).
using System; namespace ConsoleApp6 { class Triangle { // Internal fields of the class - coordinates of the extreme points of the triangle private double x1, y1, x2, y2, x3, y3; // Конструктор public Triangle(double x1, double y1, double x2, double y2, double x3, double y3) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; } // An operator method that overloads the unary operator !. // The method returns true if the lengths of the sides are equal to 5 decimal places public static bool operator!(Triangle tr) { // Precision - 5 decimal places double eps = 1E-5; // Distance between points 1 - 2 double a = Math.Sqrt((tr.x1 - tr.x2) * (tr.x1 - tr.x2) + (tr.y1 - tr.y2) * (tr.y1 - tr.y2)); // Distance between points 1 - 3 double b = Math.Sqrt((tr.x1 - tr.x3) * (tr.x1 - tr.x3) + (tr.y1 - tr.y3) * (tr.y1 - tr.y3)); // Distance between points 2 - 3 double c = Math.Sqrt((tr.x2 - tr.x3) * (tr.x2 - tr.x3) + (tr.y2 - tr.y3) * (tr.y2 - tr.y3)); return (Math.Abs(a - b) < eps) && (Math.Abs(b - c) < eps) && (Math.Abs(a - c) < eps); } } internal class Program { static void Main(string[] args) { // Create the instance of Triangle class Triangle tr = new Triangle(1, 1, 2, 2, 3, 1); // Call the overloaded Triangle::operator!() if (!tr) Console.WriteLine("The sides of the triangle are equal"); else Console.WriteLine("The sides of the triangle are not equal"); Console.ReadKey(); } } }
Result
The sides of the triangle are not equal
⇑
8. Example of overloading unary operators ++, — (increment, decrement)
The unary increment (++) and decrement (–) operators can also be overloaded. There is no difference in C# when overloading the prefix or postfix form of the increment and decrement operators. The prefix form is overloaded, which has the same effect as the postfix form.
The example implements the Point class, which describes a point on the coordinate plane. For demonstration purposes, operator functions are overloaded in the class
public static Point operator++(Point pt); public static Point operator--(Point pt);
In these functions, the value of the x, y coordinates increases and decreases by 1, respectively.
using System; namespace ConsoleApp6 { class Point { // Internal fields - coordinates of a point private double x, y; // Constructor public Point(double x, double y) { this.x = x; this.y = y; } // Properties of access to internal fields public double X { get { return x; } set { x = value; } } public double Y { get { return y; } set { y = value; } } // A method that prints the internal state of a class public void Print(string msg) { Console.WriteLine(msg + " => ( " + x + "; " + y + ")"); } // Methods that overload the increment (++) and decrement (--) operators public static Point operator++(Point pt) { return new Point(pt.x + 1, pt.y + 1); } public static Point operator--(Point pt) { return new Point(pt.x - 1, pt.y - 1); } } internal class Program { static void Main(string[] args) { // 1. Declare an instance of the Point class Point pt1 = new Point(2, 8); // 2. Call the postfix form of the increment operator ++ pt1++; // the overloaded ++ operator for the Point class is called // 3. Print the state of the pt1 instance pt1.Print("pt1"); // pt1 => ( 3; 9) // 4. Call the prefix form of decrement operator -- --pt1; // 5. Display state of instance pt1 again pt1.Print("pt1"); // pt1 => ( 2; 8) Console.ReadKey(); } } }
Result
pt1 => ( 3; 9) pt1 => ( 2; 8)
⇑
9. Example of overlading unary operator ~ (addition to 1)
The example demonstrates overloading the unary ~ (tilde) operator.
The Integer class is declared, which describes a non-negative integer. The following operator method is declared in the class
public static Integer operator~(Integer num)
which overloads the ~ operator. The method returns an instance of the Integer class in which the number is reversed (read in reverse order).
using System; namespace ConsoleApp6 { // A class that describes an integer value // that can only be positive and has additional properties class Integer { // Internal field - number private int value; // Constructor public Integer(int value) { if (value < 0) this.value = -value; else this.value = value; } // Access properties public int Value { get { return value; } set { if (value < 0) this.value = -value; else this.value = value; } } // The ~ operator overload method // The method inverts the number. For example, 2351 => 1532 public static Integer operator~(Integer num) { int result = 0; int t; int pow; // Determine the order of the number t = num.Value / 10; pow = 1; while (t > 0) { t = t / 10; pow *= 10; } // Form the resulting number t = num.Value; while (t>0) { result = result + (t % 10) * pow; t = t / 10; pow = pow / 10; } return new Integer(result); } // The method that outputs the internal field. public void Print(string msg) { Console.WriteLine(msg + " => " + value); } } internal class Program { static void Main(string[] args) { // Declare an instance of the Integer class Integer num1 = new Integer(25631); // Display the instance value num1.Print("num1"); // Call a method that overloads the ~ operator Integer num2 = ~num1; // Display the result num2.Print("num2"); Console.ReadKey(); } } }
Result
num1 => 25631 num2 => 13652
⇑
Related topics
- Overloading binary operators. Operator overloading +, –, *, /, %. Nesting arbitrary logic on overload
- Overloading comparison operators ==, !=, <, >, <=, >=. Overloading boolean bitwise operators &, |, ^
⇑