Search code examples
c#functioncastingparent-childgeneric-function

Avoid having to specify T type in a generic function


I've got this generic extending function that cast an object with a specific parent type as a child type (found the code here : Unable to Cast from Parent Class to Child Class) :

public static U ParentToChild<T, U>(this T parent) {
    if(!typeof(U).IsSubclassOf(typeof(T)))
        throw new Exception(typeof(U).Name + " isn't a subclass of " + typeof(T).Name);
    var serializedParent = JsonConvert.SerializeObject(parent);
    return JsonConvert.DeserializeObject<U>(serializedParent);
}

So when I call this function I need to specify both Parent and Child class type like :

Child child = parent.ParentToChild<Parent, Child>();

Is there any way to avoid the 'Parent' precision ?

I would like to write this :

Child child = parent.ParentToChild<Child>();

Solution

  • You can make object the parameter type and remove the type parameter T altogether:

    public static U ParentToChild<U>(this object parent) {
        // note how I used "parent.GetType()" instead of `typeof(T)`
        if (!typeof(U).IsSubclassOf(parent.GetType()))
            throw new Exception(typeof(U).Name + " isn't a subclass of " + parent.GetType().Name);
        var serializedParent = JsonConvert.SerializeObject(parent);
        return JsonConvert.DeserializeObject<U>(serializedParent);
    }
    

    By the way, your method isn't making full use of the generic type parameter T anyway. You could have used it as a constraint for U, avoiding a runtime check:

    public static U ParentToChild<T, U>(this T parent) where U : T {
        //                                            ^^^^^^^^^^^^^
        var serializedParent = JsonConvert.SerializeObject(parent);
        return JsonConvert.DeserializeObject<U>(serializedParent);
    }
    

    So if you use object as the parameter, you lose this compile-time type checking.