Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET generics terminology - open/closed, unbound/constructed

Tags:

.net

generics

.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?

like image 989
Konstantin Avatar asked Feb 02 '11 15:02

Konstantin


People also ask

What is unbound generic 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 (§11.7.

What are open generics?

An "open generic type" is just a generic type that doesn't yet have its type specified (e.g., CargoCrate<T> ).

What are closed generics?

As noted in the Subsequent Procedures Policy Development Process Working Group (SubPro PDP WG) Final Report, a closed generic is "a TLD representing a string that is a generic name or term under which domains are registered and usable exclusively by the registry operator or its affiliates."

What does generic<> mean in c#?

What Does Generics Mean? Generics refer to a feature in C# that allows defining a class or method with type as a parameter. Generics allow for designing a classes and methods whose types are specified only at the time of declaration and instantiation.


1 Answers

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.
like image 178
Ani Avatar answered Oct 25 '22 00:10

Ani