The documentation of the instance property Type.IsConstructedGenericType is unclear or misleading.
I tried the following code to find the actual behavior of this and related properties:
// create list of types to use later in a Dictionary<,> var li = new List<Type>(); // two concrete types: li.Add(typeof(int)); li.Add(typeof(string)); // the two type parameters from Dictionary<,> li.Add(typeof(Dictionary<,>).GetGenericArguments()[0]); li.Add(typeof(Dictionary<,>).GetGenericArguments()[1]); // two unrelated type parameters li.Add(typeof(Func<,,,>).GetGenericArguments()[1]); li.Add(typeof(EventHandler<>).GetGenericArguments()[0]); // run through all possibilities foreach (var first in li) { foreach (var second in li) { var t = typeof(Dictionary<,>).MakeGenericType(first, second); Console.WriteLine(t); Console.WriteLine(t.IsGenericTypeDefinition); Console.WriteLine(t.IsConstructedGenericType); Console.WriteLine(t.ContainsGenericParameters); } } The code runs through a Cartesian product consisting of 36 types t.
Results: For 32 types (all but the 4 combinations Dictionary<int, int>, Dictionary<int, string>, Dictionary<string, int>, Dictionary<string, string>), the value of ContainsGenericParameters was true.
For 35 types, IsGenericTypeDefinition was false while IsConstructedGenericType was true. For the last type, namely (unsurprisingly):
System.Collections.Generic.Dictionary`2[TKey,TValue] the IsGenericTypeDefinition was true and IsConstructedGenericType was false.
Can I conclude that, for a generic type, the value of IsConstructedGenericType is always the opposite (negation) of IsGenericTypeDefinition?
(The documentation seems to claim that IsConstructedGenericType is instead the opposite of ContainsGenericParameters, but we clearly exhibited a lot of counterexamples to that.)