private static ReadOnlyCollection <Type> GetConcreteTypesCore(Type genericType, LinkList <Binding> bindings)
        {
            Debug.Assert(genericType != null);
            Debug.Assert(bindings != null);

            bool cached  = concreteTypeCache_.ContainsKey(genericType);
            bool unbound = genericType.GetGenericArguments( )
                           .All((a) => !Binding.ContainsArgument(bindings, a));

            // If the type has already been evaluated and there are no interfering bindings, return cached value.
            if (cached && unbound)
            {
                return(concreteTypeCache_[genericType]);
            }


            // Otherwise, get a concrete type for each set of bindings.
            LinkList <Type>   openArguments;
            BindingCollection concreteTypeBindngs = GenericTypeResolver.GetConcreteTypeBindings(genericType, bindings, out openArguments);
            var concreteTypes = concreteTypeBindngs
                                .Transform((argumentBindings) => MakeConcreteType(genericType, openArguments, argumentBindings))
                                .ToReadOnlyCollection( );

            // If there are no interfering bindings, cache the concrete types.
            if (!cached && unbound)
            {
                concreteTypeCache_.TryAdd(genericType, concreteTypes);
                concreteTypes = concreteTypeCache_[genericType];
            }

            return(concreteTypes);
        }