Csharp/CSharp Tutorial/Operator Overload/operator overload

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

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

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


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."); 
  }   
}
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.


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);
    }
}
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

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++);
        
    }
}
Increment: 12
Increment: 13
Addition: 139
Addition: 139

Valid Overloadable Operators

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.