How does c# define +,-,*,/ operators for classes who don't have the operators overloaded? I have implemented the following class. Without overloading any operators, the mentioned operators work, and they work the way I was going to implement! Here's the code:
class Number
{
private float mDecimal;
public float Decimal
{
get { return mDecimal; }
}
private int mOrder;
public int Order
{
get { return mOrder; }
}
public Number(float dec, int pow)
{
mDecimal = dec;
mOrder = pow;
}
public Number Power(Number number)
{
throw new NotImplementedException();
}
public static implicit operator Number(float num)
{
int pow = 0;
while (num > 1000)
{
num *= 0.1f;
++pow;
}
return new Number(num, pow);
}
public static implicit operator float(Number num)
{
float result = num.mDecimal;
for (int i = 0; i < num.mOrder; ++i)
result *= 10;
return result;
}
}
Now take in account this piece of usage code:
Number n1 = 5;
Number n2 = 10;
Number n3 = n1 + n2;
n3 evaluates to 15! This happens with other operators too!
n3 = n1 + n2 is evaluated as follows:
+. Had you defined your own operator+(Number, Number) this is where it would have been selected. (You probably do want to implement it to prevent rounding errors from back-and-forth converting.)+ should be used (section 14.4.2). This is probably the most complicated part of the C# spec, but we don't need to delve into it very deeply -- all we need is the knowledge that implicit conversions apply when selecting an appropriate overload (14.4.2.1). For the precise rules, you'll also need to read section 13.4 on user-defined conversions.Number to float, the only candidate overload for + remaining after resolution is float operator +(float, float) with implicit conversions, so that is invoked.float is then implicitly converted to Number by use of the other operator. Note that even without this, you would still get a float addition, the result just wouldn't convert back. The compiler does not actually "lift" the operator, though the effect is much the same (lifting does happen for nullable versions of value types, but that's another story).When mixing types that have implicit conversions, things can get tricky. Overload resolution tries very hard to do the Right Thing and the rules are unambiguous, but even so it can be hard to see when a conversion is involved, so don't overuse implicit conversion operators. Explicit conversions require a bit more keystrokes, but it's also much easier to tell what operator will end up being invoked. This is certainly true when you're initially developing the type so you can check which operators you haven't yet implemented (but need to, for performance or precision reasons).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With