为什么我必须定义一个交换算子两次

本文关键字:交换 两次 一个 定义 为什么 | 更新日期: 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 * m2m2 * 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方法。