4

At the moment I am struggling a bit with generic typeing.

While reading about it I sometimes encounter ISomeType<>.

E.g.:

Type generic = typeof(Dictionary<,>);

https://msdn.microsoft.com/en-us/library/system.type.makegenerictype%28v=vs.110%29.aspx

I can't really find any documentation on wat the empty <> means.

So: When should I use <> or <,>?

update:

As @dcastro stated, it is called open generics and more info can be found here: Generics -Open and closed constructed Types

update 2

As for the closure argument, this question is about the meaning of the syntax.

Stefan
  • 17,448
  • 11
  • 60
  • 79
  • 2
    The comment above that example says "but keeping the comma that separates them, so the compiler can infer the number of type parameters". It might be as simple as that - it depends on the number of type parameters.. – Rup Aug 11 '15 at 13:03
  • 1
    The empty `<>` means you want to reference the un-specified type. This is typically used with reflection so you can "fill in" the `TParams` at runtime. – Aron Aug 11 '15 at 13:04
  • 4
    `ISomeType<>` is an open generic type that has one generic parameter. `Dictionary<,>` is an open generic type that has two generic parameters. For a description of what is a open generic type, the question that I've linked has a response – xanatos Aug 11 '15 at 13:04
  • The empty angle brackets basically just means "insert a type here". So for example `List<>` can be a `List` or `List`. – Mark E Aug 11 '15 at 13:05
  • Also, http://stackoverflow.com/questions/1735035/generics-open-and-closed-constructed-types – dcastro Aug 11 '15 at 13:06
  • 2
    I somewhat disagree with considering this question a duplicate of the indicated question. While this question may implicitly be answered by the answers to the other question, the other question is asking for the meaning of the term "open generic type", while this one is asking for the meaning of the syntax excerpts `<>` and `<,>`. It is like asking what `override` does on the one hand, and asking how to achieve polymorphic behaviour in a method. Both questions can essentially be answered at a time, and yet, they are two different questions that "attack" a topic from different angles. – O. R. Mapper Aug 11 '15 at 13:08

2 Answers2

5

An assembly can define, within the same namespace, multiple types with the same name, as long as the number of type arguments (generic parameters) differs for each type. Try for example:

var strA = typeof(Action).ToString();     // "System.Action"
var strB = typeof(Action<>).ToString();   // "System.Action`1[T]"
var strC = typeof(Action<,>).ToString();  // "System.Action`2[T1,T2]"
var strD = typeof(Action<,,>).ToString(); // "System.Action`3[T1,T2,T3]"

In C#, one can only use empty <...>, i.e. avoid specifying what the type parameters are, within the typeof(...) keyword.

Another example: typeof(Dictionary<,>).ToString() gives "System.Collections.Generic.Dictionary`2[TKey,TValue]". As you can see, in .NET (the CLI) the number of generic parameters is given by appending a backtick followed by digit(s).


Examples of use:

static bool IsDictionary(object obj)
{
  if (obj == null)
    return false;

  var t = obj.GetType();
  return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>);
}

static object GetDictionary(object a, object b)
{
  var t = typeof(Dictionary<,>).MakeGenericType(a.GetType(), b.GetType());
  return Activator.CreateInstance(t);
}

But if possible, avoid reflection and use compile-time types, for example (not quite equivalent to the above):

static Dictionary<TA, TB> GetDictionary<TA, TB>(TA a, TB b)
{
  return new Dictionary<TA, TB>();
}
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • I see. And can I conform your example compare `typeof(Action<,>)` in any way to `typeof(Action`? What I mean is; are there any good uses for getting `typeof(Action<,>)`? – Stefan Aug 11 '15 at 22:23
  • @Stefan You mostly use `typeof` when you do reflection. In most other situations, you want `Action` where the types `Foo` and `OtherFoo` could be classes (or interfaces, structs, enums, delegate types, or array types) or could be type parameters of your own generic classes (interfaces, structs, delegate types) or of your own generic methods. – Jeppe Stig Nielsen Aug 11 '15 at 22:31
  • 1
    I added some (simplified) uses. – Jeppe Stig Nielsen Aug 11 '15 at 22:52
3

You'll use <,> when you're creating a generic type that accepts multiple type parameters, and <> when your type accepts a single parameter.

For example, Dictionaries are instantiated with a key/value pair where you must define the type of both the key and value, so you pass a type argument for both key and value.

Dictionary<type1,type2> myDictionary = new Dictionary<type1,type2>();

On the other hand, Lists accepts only a single type parameter.

List<type> myList = new List<type>();
Jerreck
  • 2,930
  • 3
  • 24
  • 42