Covariance, contravariance and eliminating superfluous type parameters

Given the following class hierarchy:

abstract class A {  }
abstract class B {  }
abstract class C {  }
abstract class D<TA, TB, TC>
  where TA : A
  where TB : B
  where TC : C {  }

class E : A {  }
class F : B {  }
class G : C {  }
class H : D<E, F, G> {  }

I want to create a simple generic method to instantiate an object of type D:

void Create<TD>(string description)
  where TD : D
{
  var instance = Activator.CreateInstance<TD>();
}

But the compiler forces the type parameters for D to be specified, hence I have to write the following:

void Create<TD, TA, TB, TC>(string description)
  where TA : A
  where TB : B
  where TC : C
  where TD : D<TA, TB, TC>
{
  var instance = Activator.CreateInstance<D>();
}

Which means that instead of being able to write

Create<H>("foo");

I have to write

Create<H, E, F, G>("foo");

My question is: since I'm specifying H as the concrete instance, why does the compiler require the additional type parameters for the base class D on the method signature? Why can't it simply infer those from H?

Upvotes: 2

Views: 187

Answers (1)

Roland Mai
Roland Mai

Reputation: 31077

where TD : D implies D is not generic, where as where where TD : D<TA, TB, TC> implies that D is generic.

Upvotes: 2

Related Questions