47

I'm reading book "the C# programming Language", 4th Edition, by Anders Hejlsberg etc.

There are several definitions that are a bit twisting:

unbound generic type: A generic type declaration, by itself, denotes an unbound generic type ...

constructed type: A type that includes at least one type argument is called a constructed type.

open type: An open type is a type that involves type parameters.

closed type: A closed type is a type that is not an open type.

unbound type: refers to a nongeneric type or an unbound generic type.

bound type: refers to a nongeneric type or a constructed type. [annotate] ERIC LIPPERT: Yes, nongeneric types are considered to be both bound and unbound.

Question 1, is below what I listed correct?

int                     //non-generic, closed, unbound & bound, 
class A<T, U, V>        //generic,     open,   unbound, 
class A<int, U, V>      //generic,     open,   bound, constructed 
class A<int, int, V>    //generic,     open,   bound, constructed
class A<int, int, int>  //generic,     closed, bound, constructed

Question 2, The books says "An unbound type refers to the entity declared by a type declaration. An unbound generic type is not itself a type, and it 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)." Fine, but below is a small testing program that can compile:

public class A<W, X> { }

// Q2.1: how come unbounded generic type A<W,X> can be used as a base type?
public class B<W, X> : A<W, X> { } 

public class C<T,U,V>
{
    // Q2.2: how come unbounded generic type Dictionary<T, U> can be used as a return value?
    public Dictionary<T,U> ReturnDictionary() { return new Dictionary<T, U>(); }

    // Q2.3: how come unbounded generic type A<T, U> can be used as a return value?
    public A<T, U> ReturnB() { return new A<T, U>(); }
}
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
athos
  • 6,120
  • 5
  • 51
  • 95
  • For what I know about the 2nd questions. You can only use class B and class C given parameters for the template class types so you'll only use them completely bound. – CodingBarfield Jul 07 '11 at 07:10
  • Yes, that's could be a bit misleading. Obviously you can use an unbound type inside a **definition** of a parent unbound type (with same unbound generic parameters), but you can never instantiate it on its own. – vgru Jul 07 '11 at 07:27
  • possible duplicate of [What exactly is an "open generic type" in .NET?](http://stackoverflow.com/questions/2173107/what-exactly-is-an-open-generic-type-in-net) – nawfal May 14 '13 at 04:57
  • @nawfal that question is a duplicate itself. – Izzy May 14 '13 at 15:14
  • @Izzy Yes, but the way this is titled, I believe *that question* points more to this. – nawfal May 14 '13 at 15:20

2 Answers2

31

These are examples of unbound generic types:

  • List<>
  • Dictionary<,>

They can be used with typeof, i.e., the following are valid expressions:

  • typeof(List<>)
  • typeof(Dictionary<,>)

That should answer your question 2. With respect to question 1, note that type arguments can be constructed types or type parameters. Thus, your list should be updated as follows:

public class MyClass<T, U> {  // declares the type parameters T and U

    // all of these are
    // - generic,
    // - constructed (since two type arguments are supplied), and
    // - bound (since they are constructed):

    private Dictionary<T, U> var1;     // open (since T and U are type parameters)
    private Dictionary<T, int> var2;   // open (since T is a type parameter)
    private Dictionary<int, int> var3; // closed
}
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • i think my misunderstanding was, for MyClass, I thought T & U are not type parameters, I thought only "int" in "MyClass" is type parameter. – athos Jul 07 '11 at 09:06
  • @athos: Yes, it's exactly the opposite: `int` is *not* a type parameter, but `T` and `U` are. *Both* can be used as *type arguments* (i.e., for replacing the underscores in `private Dictionary<_, _> var1`). – Heinzi Jul 07 '11 at 09:14
  • 4
    @athos: Heinzi is correct. To clarify further. T and U are type *parameters* where they are *declared*. They can then be *used* as type arguments, or just used as types. By analogy, suppose you had: `int foo(int x){ return bar(x); }` Here "x" is a *parameter of foo* where it is declared and an *argument of a call to bar* where it is used. Type parameters and type arguments work similarly. – Eric Lippert Jul 07 '11 at 21:34
  • @Heinzi how is `Dictionary` constructed? I think a constructed type *is an open type if and only if one or more of its type arguments is an open type.* – nawfal May 14 '13 at 12:00
  • @nawfal: This is the definition for *open type*, not the definition for *constructed type*. `Dictionary` is not an open type. – Heinzi May 14 '13 at 13:55
  • @Heinzi Yes I agree, I got the definition wrong, I will update my answer. Btw I didn't mean `Dictionary` is open type; I was doubtful of if it being constructed type, which it really is. Sorry for the confusion. – nawfal May 14 '13 at 14:57
  • @Heinzi is `Dictionary` constructed? According to Jon's explanation [here](http://stackoverflow.com/a/1735060/661933), *A constructed type has at least one type argument specified*.. – nawfal May 15 '13 at 07:26
  • @nawfal: Yes, it is. It has two type arguments specified: `T` and `U`. `Dictionary<,>` would not be constructed, since it has no type arguments specified. – Heinzi May 15 '13 at 08:18
  • @Heinzi so that means all bound generic types are basically constructed, is it? I thought, *by specified*, it means a real type like `int`. – nawfal May 15 '13 at 08:20
  • @nawfal: Yes. A bound type *is defined as* a nongeneric type or a constructed type. – Heinzi May 15 '13 at 08:22
  • @Heinzi that makes sense. Where do you get these formal definitions from? A sense of understanding, or documented somewhere? – nawfal May 15 '13 at 08:24
  • 1
    @nawfal: It's documented in the [C# language specification](http://www.microsoft.com/en-us/download/details.aspx?id=7029). For example, section 4.4.3 states: "The term *bound type* refers to a non-generic type or a constructed type." – Heinzi May 15 '13 at 08:46
  • What is exactly the usage of unbound generics? I cannot figure out when I may need them. – Mohammed Noureldin Dec 31 '17 at 11:10
  • 1
    @MohammedNoureldin you can use them like `typeof(List<>)`. Things like that are handy if you dig deep into reflection. For e.g. constructing a generic type. See this answer for a sample usage: https://stackoverflow.com/a/8940014/661933 – nawfal Jun 15 '19 at 01:34
8

An excellent answer is given by Jon, here.

Not giving a technical description since everything is there perfectly in the linked answer. To merely replicate the gist of it as an answer here, it would look like:

A                             //non generic, bound
A<U, V>                       //generic,     bound,  open,   constructed
A<int, V>                     //generic,     bound,  open,   constructed
A<int, int>                   //generic,     bound,  closed, constructed
A<,> (used like typeof(A<,>)) //generic,     unbound 

Edited after discussion with Heinzi.

Community
  • 1
  • 1
nawfal
  • 70,104
  • 56
  • 326
  • 368