为什么我必须定义一个交换算子两次
本文关键字:交换 两次 一个 定义 为什么 | 更新日期: 2023-09-27 18:08:24
我想知道是否必须定义两次交换运算符(如*
(!
public static MyClass operator *(int i, MyClass m)
{
return new MyClass(i * m.Value);
}
public static MyClass operator *(MyClass m, int i)
{
return new MyClass(m.Value * i);
}
这背后的逻辑是什么?
其他描述:亲爱的@Marc关于向量和矩阵乘法的回答很好当且仅当我们假设操作数类型不同!!!很明显,我们只能定义一次*
算子来执行向量或矩阵乘法所以我认为这不是答案。
@马克:秩序有时在操作员中很重要。
是的,但这与不等价。顺序有时在操作数中很重要如果在*
运算符之前(或之后(使用+
运算符,可能会导致不同的结果。例如:
0 + 2 * 2 != 0 * 2 + 2
♦
假设我们已经将*
算子定义为:
public static MyClass operator *(MyClass m1, MyClass m2)
{
return new MyClass(m1.Value * m2.Value /* or some other kind of multiplication */);
}
我们不能再次定义它。
public static MyClass operator *(MyClass m2, MyClass m1) { ... }
若是这样,编译器会告诉我们类型MyClass
已经定义了一个名为"op_Multiply"的成员,该成员具有相同的参数类型。
现在,我们可以用两种方法使用这个算子:m1 * m2
或m2 * m1
,它们可能会有不同的结果,这取决于乘法过程。
顺序有时在运算符中很重要,经典的例子是子运算(-
(和除法(/
(。然而,它也可以应用于乘法:
例如,考虑它们是向量-x
是(2&倍;1(向量,y
是(1&倍;2(向量。如果我们将*
解释为矩阵乘法,那么x * y
是(2&倍;2(向量,但y * x
是(1&倍;1(向量。
因此,C#编译器并不假设二进制运算符是可交换的,即使它们通常是(加法(+
(、乘法(*
(等(。
你不必这么做-你只需要在你想写的时候这么做
MyClass x = ...;
MyClass y = x * 5;
MyClass z = 5 * x;
如果只希望底部两行中的一行有效,则可以删除另一个运算符重载。
基本上,C#语言并不认为乘法是交换的,即使是在所涉及的类型方面也是如此。
对于交换运算,您不需要实现整个操作两次,您可以引用初始运算符。例如:
public static Point operator *(Point p, float scalar)
{
return new Point(
scalar * p.mTuple[0],
scalar * p.mTuple[1],
scalar * p.mTuple[2]
);
}
public static Point operator *(float scalar, Point p)
{
return p * scalar;
}
我希望这能有所帮助。
class MyClass {
private int i;
public MyClass(int x) {
i=x;
}
public static MyClass operator+(MyClass a , MyClass b) {
return new MyClass(a.i+b.i);
}
public static implicit operator MyClass(int a) {
return new MyClass(a);
}
static void Main(string[] args) {
MyClass a , b ,c ;
a=new MyClass(2);
b=a+4;
c=4+a;
Console.WriteLine("B = {0}, C = {1}",b,c);
}
现在,您所要做的就是让编译器将int转换为MyClass实例,然后使用MyClass+MyClass方法。