Search code examples
c#operator-overloadingabstract-class

Chaining implicit operators in generic c# classes


For the following generic c# class, I'd like to convert T to K:

public abstract class ValueType<T,K> : IValueType<T> where K : ValueType<T,K>,new()
{     
    public abstract T Value { get; set; }     

    public static implicit operator ValueType<T,K>(T val) 
    {         
        K k = new K();
        k.Value = val;
        return k;    
    }
}

If I were to implement a direct operator implicit operator K(T val) it would result in a compile-time error (CS0556).

I thought I could try chaining implicit operators:

public static implicit operator K(ValueType<T,K> vt){
    return (K)val;
}

but the following example still complains that it can't be converted:

public class Test : ValueType<int, Test>
{
    public override int Value{ get; set; }
}

Test t = 6; //complains it's unable to be converted
Console.WriteLine(t.Value);

I really want to avoid explicitly casting if possible.

This question extends upon another SO question I've previously raised.


Solution

  • The rules for implementing your own implicit conversion logic are quite strict and you should probably become very familiar with sections 6.4.4 (Conversions:User-defined implicit conversions, for C# 8 section 10.2) and 10.10.3 (Classes:Conversion operators, for C# 8 section 15.10.4) of the specification if you're going to do particularly complicated ones like this.

    Briefly, a few key rules you should know are:

    • The type that you are defining the conversion in has to appear in either the "to" or "from" portion of the user-defined conversion. You can't make a class C that defines a conversion from E to F; C has got to be in there somewhere.
    • It is never possible to replace a built-in implicit conversion with one of your own; you can't make special behaviour happen when converting from C to object, for example.
    • User-defined implicit conversions will be "chained" with up to two built-in implicit conversions, but not with any other user-defined conversions. So for example, if you have a user-defined implicit conversion from C to D, and a built-in implicit conversion from D to IFoo, then you get an implicit conversion from C to IFoo. But if D has a user-defined implicit conversion to E, then you don't get an implicit conversion from C to E for free.