Determine if a generic type is open?

There are a bunch of regular, private and public types in my assembly. I have a query that I am trying to exclude public types from it

class Foo { } // a regular type
class Bar<T, U> { } // an open type
class Moo : Bar<int, string> { } // a closed type

var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => ???);
types.Foreach(t => ConsoleWriteLine(t.Name)); // should *not* output "Bar`2"

      

After debugging generic open type arguments, I found theirs to FullName

be null (as well as other things like DeclaringMethod

). So this can be one of the ways:

    bool IsOpenType(Type type)
    {
        if (!type.IsGenericType)
            return false;
        var args = type.GetGenericArguments();
        return args[0].FullName == null;
    }

    Console.WriteLine(IsOpenType(typeof(Bar<,>)));            // true
    Console.WriteLine(IsOpenType(typeof(Bar<int, string>)));  // false

      

Is there a built-in way to find out if a type is open? if not, is there a better way to do this? Thank.

+3


source to share


2 answers


You can use IsGenericTypeDefinition

:



typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false

      

+10


source


Type.IsGenericTypeDefinition is not a technically correct property to exclude public types. However, in your case it will be very good (and even in most other cases).

However, a type can be open without defining a generic type. More generally, for example, in a public method that takes a type parameter, you really want Type.ContainsGenericParameters .



See the answer to this question for more details:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters

TL; DR: the latter is recursive and the former is not, and therefore can be "tricked" by constructing a generic type that has a generic type definition as at least one of its typical type parameters.

+2


source







All Articles