運算符重載的關鍵是在對象上不能老是隻調用方法或屬性,有時還須要作一些其餘工做,例如,對數值進行相加、相乘或邏輯操做。假定已經定義了一個表示數學矩陣的類,定義矩陣的相加和相乘就必須用到運算符重載,在許多狀況下,重載運算符容許生成可讀性更高、更直觀的代碼。ide
定義一個結構Vector包含成員字段、構造函數和重寫的一個ToString()方法,最後重載運算符+和*函數
struct Vector { private double z; private double x; private double y; public double X { get => x; set => x = value; } public double Y { get => y; set => y = value; } public double Z { get => z; set => z = value; } public Vector(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } public Vector(Vector rhs) { this.x = rhs.X; this.y = rhs.Y; this.z = rhs.Z; } public override string ToString() { return "( " + X + " , " + Y + " , " + Z + " )"; } public static Vector operator +(Vector lhs, Vector rhs) { Vector result = new Vector(lhs); result.X += rhs.X; result.Y += rhs.Y; result.Z += rhs.Z; return result; } public static Vector operator *(double lhs, Vector rhs) { return new Vector(lhs * rhs.X, lhs * rhs.Y, lhs * rhs.Z); } public static Vector operator *(Vector lhs, double rhs) { return rhs * lhs; } public static double operator *(Vector lhs, Vector rhs) { return lhs.X * rhs.X + lhs.Y + rhs.Y + lhs.Z * rhs.Z; } public static bool operator ==(Vector lhs, Vector rhs) { if (lhs.Equals(rhs)) return true; else return false; } public static bool operator !=(Vector lhs, Vector rhs) { return !(lhs == rhs); } /// <summary> /// 比較兩個vector 是否相等 /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { var vector = obj as Vector?; if (obj == null) return false; if (this.X.Equals(vector.GetValueOrDefault().X) && this.Y.Equals(vector.GetValueOrDefault().Y) && this.Z.Equals(vector.GetValueOrDefault().Z)) return true; else return false; } /// <summary> /// 返回結構的HashCode /// </summary> /// <returns></returns> public override int GetHashCode() { return this.X.GetHashCode()+this.Y.GetHashCode()+this.Z.GetHashCode(); }
從上能夠看出運算符重載都聲明爲Public和static,這表示它們與它們的類結構相關聯,而不是與某個特定實例相關,因此運算符重載的代碼不能訪問非靜態成員,也不能訪問this標識符。測試
從上面咱們能夠看出在比較兩個對象相等時,使用了重寫object基類的equals方法來比較對象的屬性是否一一相等,在比較對象相等性共有四個版本:ReferenceEquals()和兩個版本的Equals(),還有比較運算符==。this
ReferenceEquals()方法是一個靜態方法,比較兩個引用是否引用類的同一個實例,特別是兩個引用是否包含內存中的相同地址。做爲靜態方法,它不能重寫,因此System.Object的實現代碼保持不變。若是提供的兩個引用引用同一個對象實例,則ReferenceEquals()老是返回true;不然就返回false。可是它認爲null等於null。spa
虛擬的Equals()方法,在本身的類中重寫它,從而按照所需來比較對象,特別是若是但願類的實例用做字典中的鍵,就須要重寫這個方法,以比較相關值。code
靜態的Equals()方法,帶有兩個參數,並對它們進行相等性比較,這個方法能夠處理兩個對象中有一個是null的狀況,靜態重載版本首先要檢查傳遞給它的引用是否爲null,若是都是null就返回true,若是隻有一個引用是null,它就返回fals,若是兩個引用實際上引用了某個對象,它就調用Equals()的虛擬實現版本,這表示在重寫Equals()的實例版本時,其效果至關於也重寫了靜態版本。對象
==在大多數狀況下的代碼表示比較引用,在結構中最好重寫比較運算符,以執行值的比較,System.String類微軟重寫了這個運算符以比較字符串的內容而不是比較它們的引用。blog
測試上面所寫結構Vector內存
// stuff to demonstrate arithmetic operations Vector vect1, vect2, vect3,vect4; vect1 = new Vector(1.0, 1.5, 2.0); vect2 = new Vector(0.0, 0.0, -10.0); vect3 = vect1 + vect2; vect4 = new Vector(1.0, 1.5, 2.0); var result = (vect4 == vect1); Console.WriteLine("vect1 = " + vect1); Console.WriteLine("vect2 = " + vect2); Console.WriteLine("vect3 = vect1 + vect2 = " + vect3); Console.WriteLine("2*vect3 = " + 2 * vect3); vect3 += vect2; Console.WriteLine("vect3+=vect2 gives " + vect3); vect3 = vect1 * 2; Console.WriteLine("Setting vect3=vect1*2 gives " + vect3); double dot = vect1*vect3; Console.WriteLine("vect1*vect3 = " + dot); Console.ReadLine();
能夠看出咱們重寫的equals()方法在對對象的值進行一一比較,其中引用了double結構重寫的equals方法字符串