There is a maxim in API design: the principle of least surprise. Whatever an API does it must look obvious and self explanatory so that the developer that uses the API is not surprised by the result or any side effect of such API.
Implicit conversion operators in .NET make it so easy to surprise they should not even be considered in a good designed API.
Blaming by example
I wrote about a new member of the NMoneys family, a reference type that supplants
Money when structs are not welcome:
What I wanted to achieve was a two-way conversion between
Nullable<Money>. That conversion is perfectly safe as both types have the same null semantics.
If implicit operators from and to
Nullable<Money> are implemented, one can write code that is succint:
IEquatableComparer<MonetaryQuantity>, one could write code such as:
First two assertions pass because of the conversion of anotherFiver to
Money? before hand. For the second assertion there is no conversion going on as
Nullable<> does not implement
IEquatable<>, and there the
.Equals(object) method is called.
Surely equality is commutative (or symmetric)!
if a = b, then b = a. Right? Right? Not really, because in the first case, fiver is implicitly converted into
MonetaryQuantity beforehand, but in the second assertion, again, no one “forces” anotherFiver to convert, and therefore reference equality kicks in.
Don’t implement implicit conversions. They look cute but will bring nasty bugs when used beyond cuteness. Just don’t. Design your APIs for minimum surprise. Please.