Search code examples
c#.nettypescasting

How to convert type to generic type, whose actual type is known at the point of conversion?


I have a set of methods which simply return a stored 'object' as a different type each, like this:

bool GetAsBool();
string GetAsString();
int GetAsInt();

In the real scenario, there are currently 16 of these, and the method names are a little longer, making them not great to read. I was now looking to make it more convenient by defining a single generic method which selects the correct method from this set of "Get" methods. This would give syntax highlighting for the type passed via the generic, and make the name shorter, which I feel would be easier to read in the end. But I cannot figure out how to do the type conversion.

The generic method currently looks something like this:

T Get<T>()
{
    var returnTpe = typeof(T);
    if (returnType == typeof(bool) { return GetAsBool(); }
    else if (returnType == typeof(string) { return GetAsString(); }
    else if (returnType == typeof(int) { return GetAsInt(); }
    else { return default; }
}

This gives me Cannot implicitly convert type 'bool' to 'T' (for bool, similar for the other types). But I do know, from the if-clause, which type the T is by the time I get there. So the type of "T" and the return type of the method I select always match. This should mean the conversion is always possible, right? How do I convert my typed result back to T?

I've only tried a simple cast so far, via return (T)GetAsBool(), which gives me Cannot convert type 'bool' to 'T'. I'm no expert regarding types or generics and googling has not resulted in any more ideas on my end. Is what I'm trying to do even possible?


Solution

  • To get what you are asking for you can double-cast, first to object and then to T, and it will compile. I'm not sure how efficient this is for structs since they will probably get boxed, but it is fine for objects.

    if (returnType == typeof(bool) { return (T)(object)GetAsBool(); }
    

    But if you really want brief syntax I suggest ditching the Get method altogether and defining conversion operators instead.

    static public explicit operator bool(MyClass source) => source.GetAsBool();
    static public explicit operator string(MyClass source) => source.GetAsString();
    

    Then people using your class can just cast it to the type they want, and if the cast isn't supported, there is a compile-time error.

    var x = (bool)myObject;
    var y = (string)myObject;