为什么我必须两次定义一个可交换运算符?

我想知道我是否必须两次定义一个可交换运算符(如* )!

 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关于向量和矩阵乘法的答案是好的, 当且仅当我们假设操作数类型不同时! 很明显,我们只能定义*运算符一次来执行向量或矩阵乘法。 所以我认为这不是答案。

@Marc:订单在运营商中有时很重要。

是的,但这不等同于Order在操作数中有时很重要! 如果在*运算符之前(或之后)使用+运算符,则可以使用上述句子,这将导致不同的结果。 例如:

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+bi); } 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方法。