I’m writting a generalized method to use it in a special task at a T4 template. The method should allow me to use specialized types from a general interface. I thought about the following signatures:
interface IGreatInterface {
Object aMethodAlpha<U>(U parameter) where U : IAnInterface;
Object aMethodBeta(IAnInterface parameter)
}
public class AnInterestingClass : IAnInterface{}
When I try to implement IGreatInterface the compiler flags an error for aMethodBeta() because I’ve made my T4 to write that method using a subtype of IAnInterface (i.e. I want to implement that method like this: Object aMethodBeta(AnInterestingClass parameter)).
Method aMethodAlpha<U>() can be used but is not as clean as I want because my T4 has to generate some extra code. I (perhaps wrongly)
propose that an implementation of that method, which has to be done by a T4, could be
Object aMethodAlpha<AnInterestingClass>(AnInterestingClass parameter).
I’m thinking that generic methods do not support contravariant types but I’m not sure; I suppose that It’s the way the compiler prevents the coder to use a specific type having a method not defined in the general type…
- Does a generic method have to use the exact type when being implemented?
- Is there any trick to change this behavior?
This question is quite confusing. Let me see if I can clarify it.
That’s not legal. Simplifying somewhat:
Class
Vegetariandoes not fulfill the contract ofIEater. You should be able to pass any Food to Eat, but aVegetarianonly accepts Fruit. C# does not support virtual method formal parameter covariance because that is not typesafe.Now, you might then say, how about this:
Now we have got type safety;
Omnivorecan be used as anIFruitEaterbecause anOmnivorecan eat fruit, as well as any other food.Unfortunately, C# does not support virtual method formal parameter type contravariance even though doing so is in theory typesafe. Few languages do support this.
Similarly, C# does not support virtual method return type variance either.
I’m not sure if that actually answered your question or not. Can you clarify the question?
UPDATE:
What about:
Nope, that’s not legal either. The contract of
IEateris that you will provide a methodEat<T>that can take anyTthat is aFood. You cannot partially implement the contract, any more than you could do this:However, you can do this:
That is perfectly legal. However, you cannot do:
Because again, C# does not support virtual method formal parameter contravariance or covariance.
Note that C# does support parametric polymorphism covariance when doing so is known to be typesafe. For example, this is legal:
A sequence of fruit may be used as a sequence of food. Or,
If you have something that can compare any two fruits then it can compare any two apples.
However, this kind of covariance and contravariance is only legal when all of the following are true: (1) the variance is provably typesafe, (2) the author of the type added variance annotations indicating the desired co- and contra-variances, (3) the varying type arguments involved are all reference types, (4) the generic type is either a delegate or an interface.