Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there such a thing as a "don't care" when constraining a generic parameter to another generic interface?

Tags:

c#

generics

I have a function that accepts a generic parameter TD that I need to constrain to a generic interface. For example:

public T DefinitionPopulate<T, TD>(IDataReader dr)
    where T: class, new()
    where TD: IEntityDefinition<T, Guid>, new()
{
    T t = new T();
    TD td = new TD();
    td.DoInterfaceMethod(t, dr);
    ...
    return t;
}

However, we use many different IEntityDefinitions:

IEntityDefinition<SomeClass, Guid>
IEntityDefinition<SomeClass, int>
IEntityDefinition<SomeClass, double>
...etc...

But my function DefinitonPopulate doesn't use the second generic parameter at all, and it doesn't care what it is. But it does need to handle all of the definitions that we have in place, now and in the future. So it seems that I am stuck creating a new signature for DefinitionPopulate for every single IEntityDefinition second generic parameter that we have in place... unless...

Question: Is there some way that I can tell the compiler that I don't care what the second type parameter is? Something like a wildcard?

EDIT: I have accepted the answer that I did because it is the true answer to the question that I asked. However, this answer provides an excellent solution and is what I ended up using to resolve the underlying issue that I was having - make sure you check it out!

like image 347
Michael Bray Avatar asked Jul 05 '13 06:07

Michael Bray


3 Answers

I believe, in this case, you should have an IEntityDefinition<SomeClass> interface that all those inherit from, that is:

 interface IEntityDefinition<T>
 {
    void DoInterfaceMethod(T, DataReader);
 }

And then have the rest of the generics inherit from there:

 interface IEntityDefinition<T, TD> : IEntityDefinition<T>
 {
    // blablaba
 }

If you can't change that, you could add a third type parameter to your function generic, but that's bad design, I'd say.

like image 54
Jcl Avatar answered Oct 13 '22 19:10

Jcl


You cannot instantiate a generic type without specifying all the type parameters.

Probably the best you can do is to add that unused type parameter of the interface to your generic type paramaters:

public T DefinitionPopulate<T, TD, DontCare>(IDataReader dr)
    where T: class, new()
    where TD: IEntityDefinition<T, DontCare>, new()

This allows you not to care when writing the generic code, but naturally any specialisations will need to supply that type.

like image 35
David Heffernan Avatar answered Oct 13 '22 21:10

David Heffernan


No wildcards - you'll have to add a third generic parameter to your definition, purely to allow the flexibility:

public T DefinitionPopulate<T, TD,TOther>(IDataReader dr)
    where T: class, new()
    where TD: IEntityDefinition<T, TOther>, new()
like image 32
Damien_The_Unbeliever Avatar answered Oct 13 '22 21:10

Damien_The_Unbeliever