要求重载方法的参数至少有一个参数与重载方法的类型一样。
运算符参数不能使用ref/out修饰符。
需许要注意的要点如下:
- &&和||不能被直接重载,但使用&和|进入计算则可以被重载
- [ ]不能被重载,可以使用索引器来代替它完成所需操作
- ( )不能被重载,代替此运算符的方式是定义新的转换运算符 ,即隐式/显示转换运算符
- 逻辑运算符必须成对重载==和!=
- 赋值运算符=不能被重载, +=也属于赋值运算符
//operator是运算符重载的关键字
//重载二元运算符
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();
result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;
return result;
}
//可以多次重载同一运算符
public static ThreeD operator -(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();
result.x = op1.x - op2.x;
result.y = op1.y - op2.y;
result.z = op1.z - op2.z;
return result;
}
//重载一元运算符
public static ThreeD operator -(ThreeD op)
{
ThreeD result = new ThreeD();
result.x = -op.x;
result.y = -op.y;
result.z = -op.z;
return result;
}
//重载二元运算符
public static ThreeD operator +(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();
result.x = op1.x + op2.x;
result.y = op1.y + op2.y;
result.z = op1.z + op2.z;
return result;
}
//可以多次重载同一运算符
public static ThreeD operator -(ThreeD op1, ThreeD op2)
{
ThreeD result = new ThreeD();
result.x = op1.x - op2.x;
result.y = op1.y - op2.y;
result.z = op1.z - op2.z;
return result;
}
//重载一元运算符
public static ThreeD operator -(ThreeD op)
{
ThreeD result = new ThreeD();
result.x = -op.x;
result.y = -op.y;
result.z = -op.z;
return result;
}
对象+整型 与 整型 + 对象 是不一样的,所以要重载两次:
public static ThreeD operator +(ThreeD op1, int op2)
{
ThreeD result = new ThreeD();
result.x = op1.x + op2;
result.y = op1.y + op2;
result.z = op1.z + op2;
return result;
}
public static ThreeD operator +(int op1, ThreeD op2)
{
ThreeD result = new ThreeD();
result.x = op1 + op2.x;
result.y = op1 + op2.y;
result.z = op1 + op2.z;
return result;
}
{
ThreeD result = new ThreeD();
result.x = op1.x + op2;
result.y = op1.y + op2;
result.z = op1.z + op2;
return result;
}
public static ThreeD operator +(int op1, ThreeD op2)
{
ThreeD result = new ThreeD();
result.x = op1 + op2.x;
result.y = op1 + op2.y;
result.z = op1 + op2.z;
return result;
}
重载关系运算符要“成对重载”,比如说<和>,不能只重载其中重载一个。先重载<,然后可以利用<重载>:
public static bool operator <(ThreeD op1, ThreeD op2)
{
if ((op1.x < op2.x) && (op1.y < op2.y) && (op1.z < op2.z))
{
return true;
}
else
{
return false;
}
}
public static bool operator >(ThreeD op1, ThreeD op2)
{
if (op1 < op2)
{
return false;
}
else
{
return true;
}
}
{
if ((op1.x < op2.x) && (op1.y < op2.y) && (op1.z < op2.z))
{
return true;
}
else
{
return false;
}
}
public static bool operator >(ThreeD op1, ThreeD op2)
{
if (op1 < op2)
{
return false;
}
else
{
return true;
}
}
关系运算符==,重载时候需要同时覆写Equal(object)方法和GetHashCode()方法,如下:
public static bool operator ==(ThreeD a, ThreeD b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.x == b.x && a.y == b.y && a.z == b.z;
}
public static bool operator !=(ThreeD op1, ThreeD op2)
{
return !(op1 == op2);
}
public override bool Equals(Object obj)
{
if (obj == null)
{
return false;
}
ThreeD p = obj as ThreeD;
if ((object)p == null)
{
return false;
}
return ((this.x == p.x) && (this.y == p.y) && (this.z == p.z));
}
public override int GetHashCode()
{
return x ^ y ^ z;
}
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.x == b.x && a.y == b.y && a.z == b.z;
}
public static bool operator !=(ThreeD op1, ThreeD op2)
{
return !(op1 == op2);
}
public override bool Equals(Object obj)
{
if (obj == null)
{
return false;
}
ThreeD p = obj as ThreeD;
if ((object)p == null)
{
return false;
}
return ((this.x == p.x) && (this.y == p.y) && (this.z == p.z));
}
public override int GetHashCode()
{
return x ^ y ^ z;
}
重载true和false,也要成对出现,同上。可以认为true/false也是运算符。
重载逻辑运算符,一共5个:& | ! && ||
!只是对true的取反,很容易实现。
&&与||是不能被重载的,编译器会报错。只有通过实现&与|的重载,还要实现true与false的重载,同时满足:
重载的&与|的返回类型与参数类型必须是 重载运算符的类型。
实现如下:ThreeD定义见前面
public static ThreeD operator &(ThreeD op1, ThreeD op2)
{
if ((op1.x != 0) && (op1.y != 0) && (op1.z != 0) &
(op2.x != 0) && (op2.y != 0) && (op2.z != 0)
)
{
return new ThreeD(1, 1, 1);
}
else
{
return new ThreeD(0, 0, 0);
}
}
这样,&&与||对象自动可用,操作如下:如果重载的true(对应||)或false(对应&&)检验第一个操作数,如果它能确定运算的结果,那么直接返回,否则,使用相应的重载&或|来判断结果——短路运算符的原理。{
if ((op1.x != 0) && (op1.y != 0) && (op1.z != 0) &
(op2.x != 0) && (op2.y != 0) && (op2.z != 0)
)
{
return new ThreeD(1, 1, 1);
}
else
{
return new ThreeD(0, 0, 0);
}
}
转换运算符:
有两种:隐式(implicit)和显示(explicit)
implicit转换,自动调用转换方法。
explicit转换,要强制转换类型。
public static implicit operator int(ThreeD op)
{
return op.x * op.y * op.z;
}
public static explicit operator String(ThreeD op)
{
return op.x.ToString() + op.y.ToString() + op.z.ToString();
}
static void Main(string[] args)
{
int i = c;
String s = (String)c;
}
{
return op.x * op.y * op.z;
}
public static explicit operator String(ThreeD op)
{
return op.x.ToString() + op.y.ToString() + op.z.ToString();
}
static void Main(string[] args)
{
int i = c;
String s = (String)c;
}
转换操作符的约束:
不能定义从double到int的类型转换,可以实现自定义类型与系统类型的转换。
不能定义Object和其他自定义类型的转换。
不能给相同的源和目标同时定义implicit和explicit转换。
不能定义基类到派生类的转换。
不能定义接口到其他类型的转换。
implicit和explicit的选择:
隐式转换至用于与在转换不会引起错误的环境,满足以下两条才创建隐式转换:
1.不丢失信息,如截断/溢出/丢失正负号
2.转换不会引起异常。
复合运算符不能被重载,因为它们总是被分解开来,如+= ,但是,如果已经重载了+,那么+=就自动可以使用