.NET generics terminology - open/closed, unbound/constructed
Asked Answered
A

1

15

.NET generics terminology is a bit ambiguous. Even worse - it seems to be used ambiguously and differently in different sources. What basically is not clear is relationships between these 4 terms (in relation to "Type"):

  1. open
  2. closed
  3. unbound
  4. constructed

I understand that List<T> is open and List<int> is closed. But what really is "constructed" and "unbound" in relation to open/closed types?

Aracelis answered 2/2, 2011 at 15:52 Comment(0)
D
22

From the language specification:

4.4 Constructed types

A generic type declaration, by itself, denotes an unbound generic type that is used as a “blueprint” to form many different types, by way of applying type arguments. The type arguments are written within angle brackets (< and> ) immediately following the name of the generic type. A type that includes at least one type argument is called a constructed type. A constructed type can be used in most places in the language in which a type name can appear. An unbound generic type can only be used within a typeof-expression (§7.6.11). [...]

4.4.2 Open and closed types

All types can be classified as either open types or closed types. An open type is a type that involves type parameters. More specifically:

• A type parameter defines an open type.

• An array type is an open type if and only if its element type is an open type.

• A constructed type is an open type if and only if one or more of its type arguments is an open type. A constructed nested type is an open type if and only if one or more of its type arguments or the type arguments of its containing type(s) is an open type.

A closed type is a type that is not an open type. [...]

4.4.3 Bound and unbound types

The term unbound type refers to a non-generic type or an unbound generic type. The term bound type refers to a non-generic type or a constructed type. An unbound type refers to the entity declared by a type declaration. An unbound generic type is not itself a type, and cannot be used as the type of a variable, argument or return value, or as a base type. The only construct in which an unbound generic type can be referenced is the typeof expression (§7.6.11).


Here's an example I thought of:

// Foo<T> is an unbound generic type.
class Foo<T> { .. } 

// Bar<K> is an unbound generic type.
// Its base-class Foo<K> is a constructed, open generic type.
class Bar<K> : Foo<K> { .. } 

// IntFoo is not a generic type.
// Its base-class Foo<int> is a constructed, closed generic type.
class IntFoo : Foo<int> { .. } 

And here's an attempt to tie that in with the reflection API, using the relevant properties: IsGenericType, IsGenericTypeDefinition and ContainsGenericParameters

(These tests are not 100% predictive of each "kind" as per the language spec).

+----------+---------------------+-----------+--------------+-------------------+
|   Name   |        Kind         | IsGenType | IsGenTypeDef | ContainsGenParams |
+----------+---------------------+-----------+--------------+-------------------+
| Foo<>    | Unbound             | TRUE      | TRUE         | TRUE              |
| Foo<>*   | Constructed, open   | TRUE      | FALSE        | TRUE              |
| Foo<int> | Constructed, closed | TRUE      | FALSE        | FALSE             |
| IntFoo   | Not generic         | FALSE     | FALSE        | FALSE             |
+----------+---------------------+-----------+--------------+-------------------+
* = Bar<>'s base type.
Dunois answered 2/2, 2011 at 15:58 Comment(2)
Also see the Examples section of the doc page for IsGenericType. For the new property IsConstructedGenericType see a thread I just started.Violoncellist
And see What exactly is an “open generic type” in .NET? (duplicate).Violoncellist

© 2022 - 2024 — McMap. All rights reserved.