private void InitializeDependencies()
{
// We track dependencies by a two-d square array that gives the known
// relationship between every pair of CType parameters. The relationship
// is one of:
//
// Unknown relationship
// known to be not dependent
// known to depend directly
// known to depend indirectly
//
// Since dependency is only defined on unfixed CType parameters, fixing a CType
// parameter causes all dependencies involving that parameter to go to
// the "known to be not dependent" state. Since dependency is a transitive property,
// this means that doing so may require recalculating the indirect dependencies
// from the now possibly smaller set of dependencies.
//
// Therefore, when we detect that the dependency state has possibly changed
// due to fixing, we change all "depends indirectly" back into "unknown" and
// recalculate from the remaining "depends directly".
//
// This algorithm thereby yields an extremely bad (but extremely unlikely) worst
// case for asymptotic performance. Suppose there are n CType parameters.
// "DependsTransitivelyOn" below costs O(n) because it must potentially check
// all n CType parameters to see if there is any k such that Xj => Xk => Xi.
// "DeduceDependencies" calls "DependsTransitivelyOn" for each "Unknown"
// pair, and there could be O(n^2) such pairs, so DependsTransitivelyOn is
// worst-case O(n^3). And we could have to recalculate the dependency graph
// after each CType parameter is fixed in turn, so that would be O(n) calls to
// DependsTransitivelyOn, giving this algorithm a worst case of O(n^4).
//
// Of course, in reality, n is going to almost always be on the order of
// "smaller than 5", and there will not be O(n^2) dependency relationships
// between CType parameters; it is far more likely that the transitivity chains
// will be very short and not branch or loop at all. This is much more likely to
// be an O(n^2) algorithm in practice.
Debug.Assert(_ppDependencies == null);
_ppDependencies = new Dependency[_pMethodTypeParameters.size][];
for (int iParam = 0; iParam < _pMethodTypeParameters.size; ++iParam)
{
_ppDependencies[iParam] = new Dependency[_pMethodTypeParameters.size];
for (int jParam = 0; jParam < _pMethodTypeParameters.size; ++jParam)
{
if (DependsDirectlyOn(iParam, jParam))
{
_ppDependencies[iParam][jParam] = Dependency.Direct;
}
}
}
DeduceAllDependencies();
}