JOEMan90
JOEMan90

Reputation: 5

Method to return derived generic class without specifying the types of the return

I have a base class like this:

public class BaseClass<T, R> : DbContext where T : class, IAPIObject<R>
{
    public void MethodA()
    {
        Something using T
        Something using R
    }
}

I have some derived classes like this:

public class DerivedClass1 : BaseClass<TypeA, TypeB>
public class DerivedClass2 : BaseClass<TypeC, TypeD>

I would like to write a function like the following, without specifying the types for the returned object, since they are defined within the derived classes:

private BaseClass GetObject<T>(T apiObject)
{
    return apiObject switch
        {
            TypeA _ => DerivedClass1(),
            TypeC _ => DerivedClass2(),
        }
}

Is this possible? Is this a good idea? I feel like there is a chance this is totally the wrong way to go about designing this thing, but I'm not too experienced.

The end goal is to be able to get an instance of BaseClass with the types defined based on some argument and then do things like BaseClass.MethodA() and not worry about specifying the types anymore:

var thing = GetObject<TypeA>(someObject);
thing.MethodA();

If I define the types on the methods themselves, then I have to define them every time I call MethodA(), which feels redundant if I know DerivedClass1 will always use TypeA and TypeB. Is there a better way to do this with a virtual method and override?

Upvotes: 0

Views: 442

Answers (1)

Sweeper
Sweeper

Reputation: 270770

Since the signature of the method that you are trying to call (MethodA) does not involve the type parameters (only its implementation uses the type parameters), you can make a non-generic interface:

interface IBaseClass {
    void MethodA();
}

// change the return type to the non-generic interface
private IBaseClass GetObject<T>(T apiObject) =>
    apiObject switch
    {
        TypeA _ => DerivedClass1(),
        TypeC _ => DerivedClass2(),
        // you seem to be missing a default case?
    };

On this non generic interface IBaseClass, you can then call MethodA!

Since you don't know anything about T and R of the returned object, you can't use any of the members of BaseClass that involve those types. IBaseClass is you promising to the compiler that "I won't use any of those members that involve T and R".

Upvotes: 1

Related Questions