何时应该使用<>(或<、>)?

4
目前我在泛型类型方面有些困难。
在阅读相关资料时,我有时会遇到 ISomeType<>

E.g.:

Type generic = typeof(Dictionary<,>);

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

我真的找不到任何关于空的<>的文档说明。

那么,什么时候应该使用<><,>

更新:

正如@dcastro所述,它被称为开放式泛型,更多信息可以在这里找到:泛型-开放和封闭构造类型

更新2:

至于闭包参数,这个问题是关于语法的含义。


2
上面的注释说“但要保留分隔它们的逗号,这样编译器才能推断类型参数的数量”。这可能就是那么简单 - 这取决于类型参数的数量。 - Rup
1
空的 <> 表示您想引用未指定的类型。这通常与反射一起使用,以便您可以在运行时“填充” TParams - Aron
4
ISomeType<>是一个开放式泛型类型,具有一个泛型参数。Dictionary<,>是一个开放式泛型类型,具有两个泛型参数。关于什么是开放式泛型类型的描述,请参考我链接的问题的回答。 - xanatos
空的尖括号基本上只是表示“在此处插入类型”。例如,List<>可以是List<string>List<int> - Mark E
另外,https://dev59.com/bHI-5IYBdhLWcg3wq6Zo - dcastro
2
我在某种程度上不同意将这个问题视为所指定问题的重复。虽然这个问题可能隐含地被其他问题的答案回答了,但是另一个问题是在问“开放泛型类型”的含义,而这个问题则是在问语法片段<><,>的含义。这就像是一方面询问override的作用,另一方面询问如何在方法中实现多态行为。这两个问题本质上可以同时回答,但它们是从不同角度“攻击”一个主题的两个不同问题。 - O. R. Mapper
2个回答

5

一个程序集可以在同一命名空间内定义多个具有相同名称的类型,只要每个类型的类型参数(泛型参数)数量不同即可。例如:

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]"

在C#中,只能在typeof(...)关键字中使用空的<...>,即避免指定类型参数。
另一个例子:typeof(Dictionary<,>).ToString()会返回"System.Collections.Generic.Dictionary`2[TKey,TValue]"。可以看到,在.NET(CLI)中,泛型参数的数量由一个反引号后跟数字来表示。
使用示例:
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);
}

但如果可能的话,避免使用反射并使用编译时类型,例如(与上面的代码不完全相同):

static Dictionary<TA, TB> GetDictionary<TA, TB>(TA a, TB b)
{
  return new Dictionary<TA, TB>();
}

我明白了。那么,我可以确认一下你的例子中typeof(Action<,>)typeof(Action<Foo,OtherFoo>)有什么相似之处吗?我的意思是,获取typeof(Action<,>)有没有什么好的用途呢? - Stefan
@Stefan 在反射时,您大多使用 typeof。在大多数其他情况下,您需要 Action<Foo, OtherFoo>,其中类型 FooOtherFoo 可以是类(或接口、结构体、枚举、委托类型或数组类型),也可以是您自己的泛型类(接口、结构体、委托类型)或您自己的泛型方法的类型参数。 - Jeppe Stig Nielsen
1
我添加了一些(简化的)用途。 - Jeppe Stig Nielsen

3

当你创建一个通用类型,可以接受多个类型参数时,使用 <,>;而当你的类型只能接受一个参数时,使用 <>。

例如,字典(Dictionaries)是通过键值对进行实例化的,必须定义键和值的类型,因此你需要为键和值分别传递类型参数。

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

另一方面,列表(Lists)只接受一个类型参数。
List<type> myList = new List<type>();

1
谢谢,但我指的是空的<> :-) 看来我没有搜索到足够多,因为这个问题似乎已经被问过了。 - Stefan
1
啊,我误解了你的问题,我的错 :) - Jerreck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接