9

I have a bunch of regular, closed and opened types in my assembly. I have a query that I'm trying to rule out the open 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"

Upon debugging the generic arguments of an open type, I found that their FullName is null (as well as other things like the DeclaringMethod) - So this could be one way:

    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 know if a type is open? if not, is there a better way to do it? Thanks.

vexe
  • 5,433
  • 12
  • 52
  • 81
  • 1
    Did you look at the documentation for `IsGenericType`? `Use the ContainsGenericParameters property to determine whether a Type object represents an open constructed type or a closed constructed type.` – Dark Falcon Sep 12 '14 at 15:19
  • 1
    You need to get all types that are open type?...var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => !t.IsGenericTypeDefinition); – terrybozzio Sep 12 '14 at 15:25
  • @Dark Falcon: Thanks for your input. This works too. I've seen `ContainsGenericParameters` pop in the intellisense but I thought it returns true if there are any generic arguments for the type. Doesn't seem so reading the doc - seems that 'argument' is not the same as 'parameter'? @terrybozzio no, the opposite, filter them out :) – vexe Sep 12 '14 at 15:25
  • in my edited comment it will filter them out... – terrybozzio Sep 12 '14 at 15:32
  • @terrybozzio noticed that, thank you +1 :) – vexe Sep 12 '14 at 15:37

2 Answers2

23

You could use IsGenericTypeDefinition:

typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
  • 1
    "You can accept an answer in 2 minutes..." ~____~ *continues bashing left click – vexe Sep 12 '14 at 15:28
  • Just found this, seems to be another way too IsConstructedGenericType http://msdn.microsoft.com/en-us/library/system.type.isconstructedgenerictype%28v=vs.110%29.aspx – vexe Sep 19 '14 at 15:12
  • @vexe: That looks like it'll work too. Although it looks like its the exact opposite of `IsGenericTypeDefinition`. – Andrew Whitaker Sep 19 '14 at 15:15
  • The .net reference source shows that if you are to close an open generic type by calling MakeGenericMethod, you must check that the type has IsGenericTypeDefinition true. So if you use the flag on MethodInfo, you should also be conforming to the expectations from .NET what constitute an open or a closed generic type. https://github.com/microsoft/referencesource/blob/master/mscorlib/system/reflection/methodinfo.cs – Tore Aurstad Jun 17 '23 at 20:19
11

Type.IsGenericTypeDefinition is not technically the correct property to rule out open types. It will however work just fine in your case (and indeed in most other cases).

That being said, a type can be open without being a generic type definition. In the more general case, e.g. in a public method that accepts a Type parameter, what you really want is Type.ContainsGenericParameters.

For full details see the answer to this question:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters

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

AnorZaken
  • 1,916
  • 1
  • 22
  • 34
  • 1
    I'm not sure why yours is not the accepted answer. The question is clearly asking whether or not a type is open. Since those "half-open" types can't be instantiated they *definitely* can't be considered closed. Anyway for this answer +1 :) – Riki Feb 13 '19 at 07:33