0

In C# is it possible to constrain the type parameter of a generic method such that it is restricted to an unclosed type of an interface in a type safe manner? Let me elaborate...

For example I have the following psuedo code:

    public bool Validate<TValidator>(object validatable)
        where TValidator : IValidator<>
    {
        // code that finds all implementations of IValidator that closes on 
        // recursive base types / interfaces of the validatable object
        // return true if validates
    }

I have several interfaces that implement IValidator such as ICreateValidator and IDeleteValidator. I can easily enough gather the validators I want in a reflection heavy not quite as generic as I'd like manner that close on all type T, and all base classes of T as well as interfaces implemented by T.

The desire would be able to call something along the lines of

    var validates = Validate<IDeleteValidator<>>(concreteDomainObject);

Which would provide me with the unclosed type of IDeleteValidator<> allowing me to internally find each implementations of IDeleteValidaor where T is either the concreteDomainObject type, an interface that the concreteDomainObject type implements, or recursive base types concreteDomainObject type extends all the way up to object.

Sure I could close the interface on the domain object, it just doesn't make sense to me that I should have to call

    Type unclosedValidatorType = typeof (TValidator).GetGenericTypeDefinition()

Given that I both could not be assured that TValidator would be a generic type at compile time, and that the explicitly closed TValidator would not be used except to strip it's closing type this seems like the wrong way of doing things to me.

The psuedo code I provided obviously function, but is there a type safe equivalent to constrian the type of generic method to an unclosed type of given interface?

edited to correct some terminology

Sam Hosseini
  • 813
  • 2
  • 9
  • 17
rheone
  • 1,517
  • 1
  • 17
  • 30
  • Can't you use `where TValidator : IValidator`? – Wutz Nov 28 '12 at 16:40
  • @Wutz I believe what you are suggesting would just define an object that closes on itself. – rheone Nov 28 '12 at 16:55
  • How do you want to use the method, and, more specifically, how do you want to use the type parameter? Why not `public bool Validate(object validatable, Type validatorType)` and `var validates = Validate(concreteDomainObject, typeof(IDeleteValidator<>));`? – phoog Nov 28 '12 at 16:58
  • @phoog My current solution is equivalent to the signature you provided , however it isn't as type safe as I would have liked as it is not possible at compile time to be sure that validatorType is a generic type nor that it is closable on concreteDomainObject. – rheone Nov 28 '12 at 17:05

1 Answers1

1

In C# is it possible to constrain the type of a generic method such that it is restricted to an unclosed type of an interface in a type safe manner?

No. Type arguments have to be closed, so it would make no sense to constrain the type parameter to type which couldn't be expressed as type arguments.

Forget the constraint part to start with - this simple code won't work:

using System;

class Test
{
    static void Main()
    {
        Foo<Action<>>();
    }

    static void Foo<T>()
    {
        Console.WriteLine(typeof(T));
    }
}

Errors:

Test.cs(7,20): error CS1525: Invalid expression term '>'
Test.cs(7,23): error CS1525: Invalid expression term ')'
Test.cs(7,24): error CS1026: ) expected
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I think the OP is asking about formal type arguments, not actual type arguments. – O. R. Mapper Nov 28 '12 at 16:41
  • @O.R.Mapper: By "formal type arguments" do you mean "type parameters"? If not, I don't know what you mean. But look at the sample call the OP wants to be able to make: `var validates = Validate>(concreteDomainObject);` – Jon Skeet Nov 28 '12 at 16:44
  • I mean the definitions of the type parameters rather than their actual values. You're right, the OP also tries to actually call a generic method with an open type as its argument (which should be closed based on information inferred from the method's parameters). – O. R. Mapper Nov 28 '12 at 16:46
  • @O.R.Mapper: Right, that's the difference between type parameters and type arguments, just like normal method parameters and method arguments. And I believe the OP *wants* to pass in the open types as type arguments... but he can't. – Jon Skeet Nov 28 '12 at 16:47
  • @O.R.Mapper I corrected by post. Sorry I was using the wrong terminology. I should have said "type parameter" not simply "type" – rheone Nov 28 '12 at 16:51
  • Ah, sorry for the confusion - my text was based on the definition that treats *argument* and *parameter* as synonyms, with *formal* and *actual* being the distinguishing mark. Well, the OP expects the suitable implementation of the interface to be picked based on the type of the object passed to the method. I'm not saying your response was wrong; I just wanted to point out that it was a bit too focused on the calling side rather than looking at the generic method declaration in the first place. – O. R. Mapper Nov 28 '12 at 16:52
  • @John Skeet, yes it was my hope to pass the open type across rather than having to manually resolve the open type from a possibly arbitrarily closed type. Which I'm doing now, I was just looking for a more type safe manner to do it. – rheone Nov 28 '12 at 16:52
  • @rheone: Yes, I realize that - I'm saying that generics in C# just don't support this use case. – Jon Skeet Nov 28 '12 at 16:54
  • @O.R.Mapper: My answer is focused on *both* - as you can't specify an open type as a type argument (as shown in the code sample), it makes sense that you can't constraint a type *parameter* to be an open type. – Jon Skeet Nov 28 '12 at 16:58