Some more on the implicit operator
Elaborating on my past post on the implicit operator in C#, here some additional information to round this thing up.
- Can you inherit the implicit operator(s)?
No, you cannot. Within a type you could write as many implicit operator implementations as you like, but any of the two types referenced must be the enclosing type. The compiler will tell you that:
error CS0556: User-defined conversion must convert to or from the enclosing type
As an example:
class Foo{ string Value { get; set; }
public static implicit operator string(Foo theFoo) { return theFoo.Value; }
public static implicit operator Foo(string theValue) { return new Foo() { Value = theValue }; }}
class Bar : Foo {}
The type “Bar” cannot do anything with the operators defined on “Foo”, hence you cannot write
Bar b = "hi";
What compiles is this:
Bar b = (Bar)(Foo)"hi";
But, as you might have guessed, you will get a runtime error. A “Foo” instance cannot be cast to a “Bar” instance.
- Any chance to do that with generics?
This contrived example will not work either:
class Implicitable<T, V> where V : Implicitable<T,V>{ T Value { get; set; }
public static implicit operator T(V theImplicitable) { return theImplicitable.Value; }}
same error.
A different restriction with its own error is when you would try this:
class Bar : Foo{ public static implicit operator Foo(Bar theValue) { return new Bar() { Value = theValue }; }}
error CS0553: '...': user-defined conversions to or from a base class are not allowed
Which makes sense after all, as it kind of leads polymorphism ad absurdum.
Lately I have come across a pattern where it appears useful to me to provide implicit operators. It is the case for generic utility classes that enhance a given type in a sort of decorator style. You can find an example here with the SingletonOf<T>. Further examples are
Monitored<T>
: It provides a decorator around a value of type T that, when changed through a property raises a ValueChanged event.Historized<T>
: It provides a decorator around a value of type T that keeps track in a Dictionary with timestamp when the value is changed and could be rolled back to some point in time.
All of those provide this pattern:
class Utility<T>{ T Value { get; set; }
public static implicit operator T(Utility<T> u) { return u.Value; }
public static implicit operator Utility<T>(T theValue) { return new Utility<T>() { Value = theValue }; }}
The boilerplate enables a simple instantiation like Utility<int> i = 3; as well as enables the Utility to behave pretty much like the type it decorates, e.g. z = i + 5; However, that is at far as it goes. To actually enable their additional behaviour you will have to keep the reference alive:
Utility<int> i = 3;i = 5; //badi.Value = 7; // good
That’s it for now. Next time, the explicit operator :)