Csharp/CSharp Tutorial/Operator Overload/operator overload

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

A better way to overload !, |, and & for TwoDimension.

This version automatically enables the && and || operators.


<source lang="csharp">using System;

class TwoDimension {

 int x, y;
  
 public TwoDimension() { 
    x = y = 0; 
 }   
 public TwoDimension(int i, int j) { 
    x = i; 
    y = j;
 }   


 // Overload | for short-circuit evaluation.   
 public static TwoDimension operator |(TwoDimension op1, TwoDimension op2)   
 {  
   if( ((op1.x != 0) || (op1.y != 0) ) | 
      ((op2.x != 0) || (op2.y != 0)) ) 
     return new TwoDimension(1, 1);   
   else   
     return new TwoDimension(0, 0);   
 }   

 // Overload & for short-circuit evaluation.   
 public static TwoDimension operator &(TwoDimension op1, TwoDimension op2)   
 {   
   if( ((op1.x != 0) && (op1.y != 0)) & 
      ((op2.x != 0) && (op2.y != 0) ) ) 
     return new TwoDimension(1, 1);   
   else   
     return new TwoDimension(0, 0);   
 }   

 // Overload !.   
 public static bool operator !(TwoDimension op)   
 {   
   if(op) return false;   
   else return true;   
 }   

 // Overload true.   
 public static bool operator true(TwoDimension op) { 
   if((op.x != 0) || (op.y != 0)) 
     return true; // at least one coordinate is non-zero 
   else 
     return false; 
 }   

 // Overload false. 
 public static bool operator false(TwoDimension op) { 
   if((op.x == 0) && (op.y == 0)) 
     return true; // all coordinates are zero 
   else 
     return false; 
 }   

 // Show X, Y
 public void show()   
 {   
   Console.WriteLine(x + ", " + y);   
 }   

}

class MainClass {

 public static void Main() {   
   TwoDimension a = new TwoDimension(5, 6);   
   TwoDimension b = new TwoDimension(10, 10);   
   TwoDimension c = new TwoDimension(0, 0);   
  
   Console.Write("Here is a: ");   
   a.show();   
   Console.Write("Here is b: ");   
   b.show();   
   Console.Write("Here is c: ");   
   c.show();   
   Console.WriteLine();   
  
   if(a) {
      Console.WriteLine("a is true."); 
   }
   
   if(b) {
       Console.WriteLine("b is true."); 
   }
   
   if(c) {
       Console.WriteLine("c is true."); 
   }
   

   if(!a) {
      Console.WriteLine("a is false."); 
   }
   if(!b) {
      Console.WriteLine("b is false."); 
   }
   if(!c) {
      Console.WriteLine("c is false."); 
   }

   Console.WriteLine(); 

   Console.WriteLine("Use & and |"); 
   if(a & b) 
      Console.WriteLine("a & b is true."); 
   else 
      Console.WriteLine("a & b is false."); 

   if(a & c) 
      Console.WriteLine("a & c is true."); 
   else 
      Console.WriteLine("a & c is false."); 

   if(a | b) 
      Console.WriteLine("a | b is true."); 
   else 
      Console.WriteLine("a | b is false."); 

   if(a | c) 
      Console.WriteLine("a | c is true."); 
   else 
      Console.WriteLine("a | c is false."); 

   Console.WriteLine(); 

   // now use short-circuit ops 
   Console.WriteLine("Use short-circuit && and ||"); 
   if(a && b) 
       Console.WriteLine("a && b is true."); 
   else 
       Console.WriteLine("a && b is false."); 

   if(a && c) 
       Console.WriteLine("a && c is true."); 
   else 
       Console.WriteLine("a && c is false."); 

   if(a || b) 
       Console.WriteLine("a || b is true."); 
   else 
       Console.WriteLine("a || b is false."); 

   if(a || c) 
       Console.WriteLine("a || c is true."); 
   else 
       Console.WriteLine("a || c is false."); 
 }   

}</source>

Here is a: 5, 6
Here is b: 10, 10
Here is c: 0, 0
a is true.
b is true.
c is false.
Use & and |
a & b is true.
a & c is false.
a | b is true.
a | c is true.
Use short-circuit && and ||
a && b is true.
a && c is false.
a || b is true.
a || c is true.

Operator Overloading: A Complex Number Class

  1. If you overload the == operator, then you need to override Equals(object) and GetHashCode().
  2. The == operator and the Equals(object) methods should function the same way.
  1. When Equals() is overridden, you should also override GetHashCode().
  2. Equals() and GetHashCode should be compatible.


<source lang="csharp">using System; struct Complex {

   float real;
   float imaginary;
   
   public Complex(float real, float imaginary)
   {
       this.real = real;
       this.imaginary = imaginary;
   }
   
   public float Real
   {
       get
       {
           return(real);
       }
       set
       {
           real = value;
       }
   }
   
   public float Imaginary
   {
       get
       {
           return(imaginary);
       }
       set
       {
           imaginary = value;
       }
   }
   
   public override string ToString()
   {
       return(String.Format("({0}, {1}i)", real, imaginary));
   }
   
   public static bool operator==(Complex c1, Complex c2)
   {
       if ((c1.real == c2.real) && (c1.imaginary == c2.imaginary))
          return(true);
       else
          return(false);
   }
   
   public static bool operator!=(Complex c1, Complex c2)
   {
       return(!(c1 == c2));
   }
   
   public override bool Equals(object o2)
   {
       Complex c2 = (Complex) o2;
       
       return(this == c2);
   }
   
   public override int GetHashCode()
   {
       return(real.GetHashCode() ^ imaginary.GetHashCode());
   }
   
   public static Complex operator+(Complex c1, Complex c2)
   {
       return(new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary));
   }
   
   public static Complex operator-(Complex c1, Complex c2)
   {
       return(new Complex(c1.real - c2.real, c1.imaginary - c2.imaginary));
   }
   
   public static Complex operator*(Complex c1, Complex c2)
   {
       return(new Complex(c1.real * c2.real - c1.imaginary * c2.imaginary,
       c1.real * c2.imaginary + c2.real * c1.imaginary));
   }
   
   public static Complex operator/(Complex c1, Complex c2)
   {
       if ((c2.real == 0.0f) && (c2.imaginary == 0.0f))
          throw new DivideByZeroException("Can"t divide by zero Complex number");
       
       float newReal = (c1.real * c2.real + c1.imaginary * c2.imaginary) / (c2.real * c2.real + c2.imaginary * c2.imaginary);
       float newImaginary = (c2.real * c1.imaginary - c1.real * c2.imaginary) / (c2.real * c2.real + c2.imaginary * c2.imaginary);
       
       return(new Complex(newReal, newImaginary));
   }
 

} class MainClass {

   public static void Main()
   {
       Complex c1 = new Complex(3, 1);
       Complex c2 = new Complex(1, 2);
       
       Console.WriteLine("c1 == c2: {0}", c1 == c2);
       Console.WriteLine("c1 != c2: {0}", c1 != c2);
       Console.WriteLine("c1 + c2 = {0}", c1 + c2);
       Console.WriteLine("c1 - c2 = {0}", c1 - c2);
       Console.WriteLine("c1 * c2 = {0}", c1 * c2);
       Console.WriteLine("c1 / c2 = {0}", c1 / c2);
   }

}</source>

c1 == c2: False
c1 != c2: True
c1 + c2 = (4, 3i)
c1 - c2 = (2, -1i)
c1 * c2 = (1, 7i)
c1 / c2 = (1, -1i)

Operator Overloading for your own class

<source lang="csharp">using System; struct MyType {

   public MyType(int value)
   {
       this.value = value;
   }
   public override string ToString()
   {
       return(value.ToString());
   }
   public static MyType operator -(MyType roman)
   {
       return(new MyType(-roman.value));
   }
   public static MyType operator +( MyType roman1, MyType roman2)
   {
       return(new MyType(roman1.value + roman2.value));
   }
   
   public static MyType operator ++(MyType roman)
   {
       return(new MyType(roman.value + 1));
   }
   int value;

} class MainClass {

   public static void Main()
   {
       MyType    roman1 = new MyType(12);
       MyType    roman2 = new MyType(125);
       
       Console.WriteLine("Increment: {0}", roman1++);
       Console.WriteLine("Increment: {0}", roman1++);
       
       Console.WriteLine("Addition: {0}", roman1 + roman2);
       Console.WriteLine("Addition: {0}", roman1++ + roman2++);
       
   }

}</source>

Increment: 12
Increment: 13
Addition: 139
Addition: 139

Valid Overloadable Operators

<source lang="csharp">C# Operator Overloadability +, -, !, ~, ++, --, true, false This set of unary operators can be overloaded. +, -, *, /, %, &, |, ^, <<, >> These binary operators can be overloaded. ==, !=, <, >, <=, >= The comparison operators can be overloaded. [] The [] operator cannot be overloaded. () The () operator cannot be overloaded. +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= Shorthand assignment operators cannot be overloaded.</source>