Home > Articles > Software Development & Management > Object Technology

This chapter is from the book

Overloading Operators

If you're an OOP programmer, you know that you can also overload operators, not just methods. You do that by defining static methods using the operator keyword. Being able to overload operators like +, -, * and so on for your own classes and structs lets you use those classes and structs with those operators, just as if they were types built into C#. C# doesn't allow as many operators to be overloaded as C++ does. You can see the possibilities for C# in Table 3.3. Note the division into unary operators and binary operators—unary operators take one operand (like the negation operator, -x), and binary operators take two operands (like the addition operator, x + y).

Table 3.3 Overloading Possibilities for C# Operators

Operators

Overloading Possibilities

+, -, !, ~, ++, --, true, false

These unary operators can be overloaded.

+, -, *, /, %, &, |, ^, <<, >>

These binary operators can be overloaded.

==, !=, <, >, <=, >=

The comparison operators can be overloaded.

&&, ||

The conditional logical operators cannot be overloaded, but they are computed with & and |, which can be overloaded.

[]

The array indexing operator cannot be overloaded, but you can define indexers in C# (see Chapter 6, "Understanding Collections and Indexers").

()

The cast operator cannot be overloaded directly, but you can define your own conversion operators, as you'll do in this chapter.

+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

Assignment operators cannot be overloaded, but if you overload a binary operator, such as +, += is also overloaded.

=, ., ?:, ->, new, is, sizeof, typeof

These operators cannot be overloaded.


Note also that, unlike C++, the = assignment operator cannot be overloaded in C#. An assignment always performs a simple bit-by-bit copy of a value into a variable. On the other hand, when you overload a binary operator like +, the corresponding compound assignment operator, +=, is automatically overloaded. Cast operations are overloaded by providing conversion methods, as we'll see in a page or two.

For C++ Programmers

Unlike C++, you cannot overload the =, (), [], &&, ||, and new operators in C#.

You can overload operators for either classes or structs. To see how this works, we'll overload the Complex struct we built earlier in the chapter (see Listing 3.6). This struct holds complex numbers like 1 + 2i, where i is the square root of -1, and we'll see how to overload operators like + so that we can add two Complex objects, or the unary negation operator so that if complex holds 1 + 2i, -complex will yield -1 - 2i. All this takes place in ch03_14.cs, which appears in Listing 3.14. We'll take this code apart in the next few sections.

Listing 3.14 Overloading Operators (ch03_14.cs)

class ch03_14
{
 public static void Main() 
 {
  Complex complex1 = new Complex(1, 2);
  Complex complex2 = new Complex(3, 4);

  System.Console.WriteLine("complex1 = {0}", complex1);
  System.Console.WriteLine("complex2 = {0}", complex2);

  Complex complex3 = -complex1;
  System.Console.WriteLine("-complex1 = {0}", complex3);

  System.Console.WriteLine("complex1 + complex2 = {0}", 
   complex1 + complex2);

  if(complex1 == complex2){
   System.Console.WriteLine("complex1 equals complex2");
  } else {
   System.Console.WriteLine("complex1 does not equal complex2");
  }
 }
}

public struct Complex 
{
 public int real;
 public int imaginary;

 public Complex(int real, int imaginary) 
 {
  this.real = real;
  this.imaginary = imaginary;
 }

 public override string ToString()
 {
  if (imaginary >= 0){
   return(System.String.Format("{0} + {1}i", real, imaginary));
  } else {
   return(System.String.Format("{0} - {1}i", real, 
   System.Math.Abs(imaginary)));
  }
 }

 public static Complex operator-(Complex complex) 
 {
  return new Complex(-complex.real, -complex.imaginary);
 }

 public static Complex operator+(Complex complex1, Complex complex2) 
 {
  return new Complex(complex1.real + complex2.real, 
   complex1.imaginary + complex2.imaginary);
 }

 public static implicit operator Complex(int theInt)
 {
  return new Complex(theInt, 0);
 }

 public static explicit operator int(Complex complex)
 {
  return complex.real;
 }

 public static bool operator==(Complex complex1, Complex complex2)
 {
  if (complex1.real == complex2.real && 
   complex1.imaginary == complex2.imaginary)
  {
   return true;
  }
  return false;
 }

 public static bool operator!=(Complex complex1, Complex complex2)
 {
  return !(complex1 == complex2);
 }

 public override bool Equals(object obj)
 {
  if (!(obj is Complex))
  { 
   return false;
  }
  return this == (Complex) obj;
 }

 public override int GetHashCode() 
 {
   return (int) System.Math.Sqrt(real * real + 
    imaginary * imaginary);
 }
}

Creating the Complex Struct

We start ch03_14.cs by using the Complex struct we saw earlier in this chapter, which has a constructor you pass the real and imaginary parts to, and we'll add the ToString method. Any time C# needs a string representation of a complex number (as when you pass it to System.Console.WriteLine), it'll call the number's ToString method:

public struct Complex 
{
 public int real;
 public int imaginary;

 public Complex(int real, int imaginary) 
 {
  this.real = real;
  this.imaginary = imaginary;
 }

 public override string ToString()
 {
  if (imaginary >= 0){
   return(System.String.Format("{0} + {1}i", real, imaginary));
  } else {
   return(System.String.Format("{0} - {1}i", real, 
   System.Math.Abs(imaginary)));
  }
 }
 .
 .
 .
}

Overloading a Unary Operator

The next step is to start overloading operators for Complex numbers. We'll start by overloading the unary negation operator, -. To do that, you add this method to the Complex struct, which uses the operator keyword and is passed a Complex number to negate:

public static Complex operator-(Complex complex) 
{
 return new Complex(-complex.real, -complex.imaginary);
}

Using System.String.Format

Note the use of System.String.Format in the previous code. This method works just like System.Console. WriteLine, except that it returns a string instead of displaying text to the console. That means we can use it to embed the real and imaginary parts of the complex number into a string.

All we have to do here is to negate the real and imaginary parts of the complex number and return the result, as you see in this code. Now if you created a complex number, 1 + 2i, and negated it like this:

Complex complex1 = new Complex(1, 2);
System.Console.WriteLine(-complex1;

You'd see this result:

-1 - 2i

Overloading a Binary Operator

We've been able to overload the - unary operator for complex numbers by adding a static method to the Complex struct that uses the operator keyword and is passed the operand to negate. When you're overloading a binary operator, like the + addition operator, you are passed two operands; in the case of the + operator, those are the complex numbers you're supposed to add. Here's the method you'd add to the Complex struct to overload the + operator for complex numbers:

public static Complex operator+(Complex complex1, Complex complex2) 
{
 return new Complex(complex1.real + complex2.real, 
  complex1.imaginary + complex2.imaginary);
}

Now if you were to use this code to add 1 + 2i and 3 + 4i:

Complex complex1 = new Complex(1, 2);
Complex complex2 = new Complex(3, 4);

System.Console.WriteLine("complex1 + complex2 = {0}", 
 complex1 + complex2);

you would see this result:

complex1 + complex2 = 4 + 6i

Overloading Conversion Operations

You can also overload conversion operations. Conversions can be either implicit or explicit, and you use the implicit or explicit keywords in those cases. The name of the operator in this case is the target type you're converting to, and the parameter you're passed is of the type you're converting from. For example, here's how to convert from an integer value to a Complex number—note that we'll just assign the integer value to the real part of the resulting complex number. Because data will be lost, we'll make this an implicit conversion:

public static implicit operator Complex(int intValue)
{
 return new Complex(intValue, 0);
}

On the other hand, converting from a complex number to an int does imply some data loss, so we'll make this an explicit conversion:

public static explicit operator int(Complex complex)
{
 return complex.real;
}

Now when you cast from Complex to int explicitly, this method will be called.

Overloading Equality Operators

Overloading the == equality operator is like overloading any binary operator, with a few differences. For one, if you overload ==, C# will insist that you overload != as well, so we'll do both operators here.

For C++ Programmers

If you overload ==, C# will insist that you also overload !=.

When you overload the == operator, you're passed two Complex objects to compare; you return true if they're equal and false otherwise. Complex numbers are equal if their real and imaginary parts are equal, so here's how to overload the == operator for complex numbers:

public static bool operator==(Complex complex1, Complex complex2)
{
 if (complex1.real == complex2.real && 
  complex1.imaginary == complex2.imaginary)
 {
  return true;
 }
  return false;
}

And here's how to overload !=:

public static bool operator!=(Complex complex1, Complex complex2)
{
  return !(complex1 == complex2);
}

If you only overload == and !=, C# will give you a warning when you compile your code that you haven't overridden the Object.Equals(object o) method. This method is sometimes used by code instead of the == operator to check for equality (in Visual Basic .NET, for example, you can't overload operators, so code would use the Equals method). For example, to check if complex1 equals complex2, you could call complex1.Equals(complex2). C# wants us to override this method, replacing the default version in the Object class, not overload it, and we'll discuss overriding methods in the next chapter. All that means in this case is that we use the override keyword here. After using the is operator to ensure that the object passed to us is a Complex object, we just compare the current object to the one passed, and return the result of that comparison, like this:

public override bool Equals(object obj)
{
 if (!(obj is Complex))
 {
  return false;
 }
 return this == (Complex) obj;
}

But there's still more to do. If you've overloaded ==,!=, and Equals, C# will still give you another warning. You haven't overridden the Object.GetHashCode method. A hash method is used to quickly generate a hash code, which is an int that corresponds to the value of an object. Hash codes allow C# to store objects more efficiently in collections, as we'll discuss in Chapter 6. You don't have to override GetHashCode—you can simply ignore the warning. In this case, we'll return the magnitude of the complex number as its hash code:

public override int GetHashCode() 
{
 return (int) System.Math.Sqrt(real * real + 
  imaginary * imaginary);
}

Now, at last, you can compare two complex numbers using the == operator, like this, which compares 1 + 2i and 3 + 4i:

Complex complex1 = new Complex(1, 2);
Complex complex2 = new Complex(3, 4);

if(complex1 == complex2){
 System.Console.WriteLine("complex1 equals complex2");
} else {
 System.Console.WriteLine("complex1 does not equal complex2");
}

Here's what this code produces:

complex1 does not equal complex2

For the full story on operator overloading, run ch03_14.cs; this example implements all the operator overloads we've discussed and puts them to work using the code we've developed. Here's what you see when you run this example:

C:\>ch03_14
complex1 = 1 + 2i
complex2 = 3 + 4i
-complex1 = -1 - 2i
complex1 + complex2 = 4 + 6i
complex1 does not equal complex2

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020