我想知道我是否必须两次定义一个可交换运算符(如*
)!
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:订单在运营商中有时很重要。
是的,但这不等同于命令在操作数中有时很重要!如果在{{1}之前(或之后)使用+
运算符,则可以使用上述句子运算符会导致不同的结果。例如:
*
♦
假设我们已将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) { ... }
已经定义了一个名为'op_Multiply'的成员,它具有相同的参数类型。
现在,我们可以通过两种方式使用此运算符:MyClass
或m1 * m2
,它们可能会有不同的结果,这取决于乘法过程。
答案 0 :(得分:33)
顺序在运算符中有时很重要,经典的例子是subraction(-
)和division(/
)。但是,它也适用于乘法:
例如,考虑它们是向量 - x
是(2×1)向量,y
是(1×2)向量。如果我们将*
解释为矩阵乘法,则x * y
是(2×2)向量,但y * x
是(1×1)向量。
因此,C#编译器不假设二元运算符是可交换的,即使它们通常是(加法(+
),乘法(*
)等等)。
答案 1 :(得分:16)
你不必这样做 - 如果你想写的话,你只需要这样做:
MyClass x = ...;
MyClass y = x * 5;
MyClass z = 5 * x;
如果您只希望底部两行的一个有效,则可以删除另一个运算符重载。
基本上,C#语言并不认为即使在涉及的类型方面,乘法也是可交换的。
答案 2 :(得分:2)
对于可交换操作,您不需要两次实现整个事物,您可以引用初始运算符。例如:
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;
}
我希望这会有所帮助。
答案 3 :(得分:0)
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方法。