I have a class (simplified for the purposes of this question) that wraps a decimal value and uses a couple of implicit operator declarations for converting between the type and the wrapped value:
private class DecimalWrapper
{
public decimal Value { get; private set; }
public DecimalWrapper(decimal value)
{
Value = value;
}
public static implicit operator decimal(DecimalWrapper a)
{
return a != null ? a.Value : default(decimal);
}
public static implicit operator DecimalWrapper(decimal value)
{
return new DecimalWrapper(value);
}
}
The usages of implicit operator here allow things like these to be done:
DecimalWrapper d1 = 5; // uses implicit operator DecimalWrapper
DecimalWrapper d2 = 10;
var result = d1 * d2; // uses implicit operator decimal
Assert.IsTrue(result.Equals(50));
Assert.IsTrue(result == 50);
Now, consider a second class (again, simplified) that has an overloaded constructor that can take a decimal or a DecimalWrapper:
private class Total
{
private readonly DecimalWrapper _total;
public Total(DecimalWrapper total)
{
_total = total;
}
public Total(decimal totalValue)
{
_total = totalValue;
}
}
I would expect to be able to instantiate an instance of Total by passing in an integer value, which would get converted to a decimal:
var total = new Total(5);
However, this results in a compiler error:
The call is ambiguous between the following methods or properties: 'Namespace.Total.Total(TypeTests.DecimalWrapper)' and 'Namespace.Total.Total(decimal)'
To fix this, you have to remove the implicit operator decimal or specify that the value 5 is in fact a decimal:
var total = new Total(5m);
This is all well and good, but I don't see why the implicit operator decimal is relevant here. So, what is going on?
Total(decimal totalValue)constructor exactly matches it.Total(DecimalWrapper total)constructor and an implicit conversionint -> decimal -> DecimalWrapper. Compiler (after it could not find the exact signature match) checks what constructors it can fulfill after type conversion, and in this case it's both.DecimalWrapper?