4

is there any way to get the following (not compiling) code running? i have not found a solution for this.

public class Factory{
    public static T Get<T>(V v)
        where T : BaseClass<V> {
            T someObject = DIContainer.Resolve<T>();
            someObject.Set(v);
    }
}

T is a normal generic type parameter, used to define the generic method "Get", but has a type constraint which contains a generic itself. Now the method should define a parameter of which the type is defined by a generic type parameter defined by the generic type parameter of the method.
BaseClass would define a method Set receiving an argument of the type of its generic type parameter.
Meaning it should be possible to call Factory.Get<A<B>>(someObjectCastableToB);.

It would work by defining the method Get as Get with another constraint on V. But then the call would be Factory.Get<A<B>,B>(....) which is not that nice as the declaration of B is there two times.

Thanks!

3
  • 1
    Where is V defined in your code snippet? Commented Aug 24, 2011 at 13:35
  • 1
    Not really. blog.slaks.net/2010/12/partial-type-inference-in-net.html Commented Aug 24, 2011 at 13:37
  • The typing of your V has to be handled somehow, so I don't see that there's anyway around including it as a generic parameter. Since you've already got a constraint on T which defines it as a BaseClass<V>, though, I don't think your call would be as bad as you may fear. I agree that Get<A<B>,B>(...) seems a bit ugly, but I don't see any reason that it couldn't just be Get<T,V>(...) where T: BaseClass<V>. I don't know if that's quite the answer you're looking for, though. Commented Aug 24, 2011 at 13:52

1 Answer 1

2

Unlike C++ templates, where you can have "template templates" or "partial specialization", C# generic arguments can only go one-deep at the declaration site, and generic constraints can only tell you about lineage and nothing more. If you want to be able to refer to the generic argument of one of your generic arguments, the only way to do that is, as you have in your example, via a generic constraint on inheritance lineage (T : BaseClass<V>), and then V must also be identified in the generic signature. You'd need something like below.

public class Factory{
    public static T Get<T, V>(V v)
        where T : BaseClass<V> {
            T someObject = DIContainer.Resolve<T>();
            someObject.Set(v);
    }
}

All I've added here is the generic argument V to your method signature. Again, if you had no base class to anchor V to, you wouldn't be able to do much about your situation. For example, if the runtime type of T itself was generic, and not its base class, you'd be stuck, as in the below sample, which would not compile.

public class Factory{
    public static T Get<T, V>(V v)
        where T : T<V> {
            T someObject = DIContainer.Resolve<T>();
            someObject.Set(v);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Same conclusion I came to. Live example: rextester.com/rundotnet?code=UMGBF54868

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.