63

Recently I noticed that generic constructed types can be open and closed. But I do not understand what they actually mean. Can you give a simple example?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
user196546
  • 2,513
  • 4
  • 23
  • 18

3 Answers3

87

In practice the terminology doesn't really matter much - I can't remember the last time I had to worry about it except when trying to write about it.

  • An unbound type has no type arguments specified
  • A constructed type has at least one type argument specified
  • A type parameter is an open type
  • An array type where the element type is open is an open type
  • An open constructed type has at least one type argument which is an open type
  • A closed type is any type which isn't open

(There are further rules for nested types. Consult the C# 3.0 spec section 4.4 for gory details.)

As an example of an open constructed type, consider:

public class NameDictionary<T> : Dictionary<string, T>

The base class of typeof(NameDictionary<>) is:

  • Constructed because it specifies type arguments
  • Open because the second type argument (T) is an open type

The MSDN docs for Type.IsGenericType have quite a useful little table.

Just to reiterate, this is almost entirely unimportant in day to day use.

I'm generally in favour of knowing the correct terminology - particularly for things like "pass by reference" etc - but in this case it really, really doesn't come up very often. I would like to actively discourage you from worrying about it :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Now a days most interview questions i faced are asked from your book.So for clarification purpose i asked. :) . – user196546 Nov 14 '09 at 18:19
  • 17
    @generixs: If someone asked me that in an interview, I would confess that I wouldn't be able to say without consulting a book or the spec :) Not a very useful interview question, I have to say. – Jon Skeet Nov 14 '09 at 18:43
  • 1
    :) give me a portion of your brain ,so that i can answer as if i were a Jon Skeet ..(sorry for kidding..). – user196546 Nov 14 '09 at 19:48
  • 1
    So in summary : if we find any type arguments then its a bound/constructed type (otherwise its unbound) and if we find any type parameters then its an open type (otherwise its closed). A closed type cannot be unbound. Did I leave any big ones out ? – explorer Oct 14 '10 at 22:15
  • @mumtaz: I'm afraid I'm too sleepy to say for sure. Basically I've *never* fully got my head round this terminology. – Jon Skeet Oct 14 '10 at 22:51
  • 3
    @Jon ... lolz... that was actually a great response. The more I read about them the more I feel like they were never intended for human consumption in the first place. – explorer Oct 14 '10 at 23:03
  • @JonSkeet, How would you describe the relationship between `List<>` and `List`? Is the latter a closed subtype of the former? A closed version of? A closed type of? – Ethan Reesor Mar 10 '15 at 17:00
  • @FireLizzard: I'd probably say it's a closed constructed type, constructed from the unbound type `List`. That's if I really had to say anything - I try hard not to talk about terminology like this. – Jon Skeet Mar 10 '15 at 17:20
  • I was reading your "C# in depth", and faced this "open and closed constructed type" term. I have decided to read more about this at StackOverflow, and finally I have found this answer here :) – Yeldar Kurmangaliyev Jun 20 '16 at 04:58
  • "C# in Depth" says that unbound type is *the form of a generic type where none of the type parameters have been provided with type arguments*. So for given type parameters `K` and `V` is `Dictionary` is an unbound type or only `Dictionary<,>` is unbound? – saidfagan Aug 16 '19 at 05:56
  • @saidfagan: I'm not sure what you mean by "for given type parameters K and V". I'd need really specific context to give an answer here - and I could be wrong, frankly. As noted in the answer, this is very rarely useful. We've even been trying to remove some of it in the ECMA spec. – Jon Skeet Aug 16 '19 at 06:50
  • @JonSkeet I mean If we are writing code inside some generic class with type parameters of `K` and `V` will `Dictionary` be unbound? Or only `Dictionary<,>` is considered an unbound type? I know these terms are unimportant, but will be good to understand them. – saidfagan Aug 24 '19 at 18:29
  • @saidfagan: It's an open constructed type - see bullets 2, 3 and 5 in the first list. – Jon Skeet Aug 24 '19 at 19:26
  • @JonSkeet OK, but is it bound or unbound? or neither of them? – saidfagan Aug 25 '19 at 07:16
  • @saidfagan: It's constructed, not unbound. (Those are opposites - see the first two bullets.) – Jon Skeet Aug 25 '19 at 07:29
  • @JonSkeet Sorry for being intrusive, but if `constructed` and `unbound` are opposites, what is the place of `bound` types between these two? – saidfagan Aug 25 '19 at 13:08
  • @saidfagan: I don't think I've referred to "bound types" anywhere here. But really, I think this has gone far enough in comments. If there are further questions, please ask in a new post - but again, it's *really* not important in 99.999% of development. – Jon Skeet Aug 25 '19 at 14:19
10

From MSDN:

A generic type or method is closed if instantiable types have been substituted for all its type parameters, including all the type parameters of all enclosing types. You can only create an instance of a generic type if it is closed.

So this works as List<int> is closed:

var list = Activator.CreateInstance(typeof(List<int>));

But this throws an exception at run-time because List<> is open:

var list = Activator.CreateInstance(typeof(List<>));
                                               ↑
dtb
  • 213,145
  • 36
  • 401
  • 431
  • 2
    In that case it's an unbound type as well though - an open, constructed type is the more esoteric kind :) – Jon Skeet Nov 14 '09 at 18:05
3

I have mostly used open generics (basically uninstantiated generics) in dependency injection mappings. For example, something like

Bind<IRepository<>>()
   .To<BasicRepository<>>()

Then, when my object constructor contains:

public SomethingController(IRepository<Something>) { ... }

My dependency injection mechanism will instantiate a BasicRepository< Something > automagically. (This works with Ninject and StructureMap, and probably the Castle Windsor library; I'm not sure about other frameworks).

JasonTrue
  • 19,244
  • 4
  • 34
  • 61
  • `Autofac` also supports open generic types: [Autofac - creating components](https://code.google.com/p/autofac/wiki/ComponentCreation#Open_Generic_Types) – sgnsajgon Oct 10 '13 at 17:52
  • As does [SimpleInjector](http://simpleinjector.readthedocs.org/en/latest/advanced.html#registration-of-open-generic-types) – Nick Jones Jul 22 '15 at 15:39