获取泛型类型参数数量

3

有没有办法获取未绑定泛型类型的参数数量?例如:

f(typeof(List<>))        => 1
f(typeof(Dictionary<,>)) => 2

更新

我知道从 Type.Name 中获取数字,但也许有一种直接从 Type 获取的方法。


3
您对由“Type”公开的操作进行了哪些研究,可以帮助您实现这一点? - Servy
术语:类型接受的通用参数数量称为该类型的“通用元数”。 - user8762691
3个回答

8

您已经拥有通用类型定义。您需要做的就是获取通用类型参数:

Type.GetGenericArguments().Length

编辑:

正如Sebastian所提到的,如果你习惯于处理C#,这可能会给你带来令人惊讶的结果,因为C#隐藏了“继承”的泛型类型参数。例如:

void Main()
{
  typeof(A<>.Nested<>).GetGenericArguments().Dump();
}

public class A<T>
{
  public class Nested<V>
  {

  }
}

这将会给你{ typeof(T), typeof(V) }。这只是.NET类的实际表现方式 - 这就是你需要引用它的方式,以及通过反射创建它的方式等。

这仅在您特别想要在与编译时未知的类有关的C#编译器中执行某些操作时才有意义;这可能意味着您正在尝试生成C#代码。似乎没有任何支持的方法可以安全地获得C#所具有的行为 - 您只需使用真正的代码生成器而不是随意拼接字符串即可 :)


1
请注意,这可能无法处理嵌套类型;例如对于OuterClass<,>.InnerClass<>,您将得到3而不是1 - Sebastian Krysmanski
@SebastianKrysmanski 嗯,这取决于你想要什么。内部类确实有三个泛型类型参数,只是C#隐藏了从更高级别的类“继承”的那些参数。如果你想复制C#的行为,你需要更加努力 :) - Luaan
@Luaan:+1。关于你回答的最后一段:计算嵌套类型的“非继承”通用参数数量实际上相当简单(只需进行另一个查询和减法运算即可);请参见我的答案的下半部分。 - stakx - no longer contributing

2
Luaan的答案”对于嵌套类型不起作用。
例如,如果你有“OuterClass<,>.InnerClass<>”,那么你会期望有一个参数“1”,但实际上.NET报告了“3”。
我发现唯一的解决方法是解析泛型类型定义的名称。
public static int GetGenericParameterCount(Type type)
{
    if (!type.IsGenericType)
    {
        return 0;
    }

    var genericTypeDefName = type.GetGenericTypeDefinition().Name;
    int tickIndex = genericTypeDefName.LastIndexOf('`');
    if (tickIndex == -1)
    {
        // This will happen for nested types like "OuterClass<int>.InnerClass".
        return 0;
    }

    return int.Parse(genericTypeDefName.Substring(tickIndex + 1), NumberStyles.None);
}

1
嵌套类确实有三个泛型类型参数。因此,除非您特别希望获得与C#编译器相同的行为,否则三是正确的答案。解析类型名称的问题在于,您所依赖的行为没有定义 - 编译器可以随时更改生成类型名称的方式,更不用说其他.NET语言具有不同的约定了。 - Luaan
你可以通过 type.GetGenericArguments().Length 来获取相同的数字,然后在嵌套类型的情况下,减去外部类型的相同指标 (type.DeclaringType)。请参见我的答案 - stakx - no longer contributing

1

计算泛型参数的总数

只需查询t.GetGenericArguments().Length即可找到某个类型t的泛型参数(或参数)的总数:

static int GenericParameterCount(this Type t)
    => t.IsGenericType ? t.GetGenericArguments().Length
                       : 0;

仅限嵌套类型:计算“本地”泛型参数的数量(不包括从外部类型继承的参数)
对于嵌套类型进行上述操作可能会得出最初令人惊讶的结果。例如,类型Outer.Inner有1个泛型参数,类型Outer.Inner有2个。只要您将这些嵌套类型仅视为Inner或Inner(即它们在源代码中声明的方式),就可能会认为这是不正确的。
(出于同样的原因,您可能会最初感到惊讶,发现typeof(Outer.Inner).IsGenericType == true,即使查询的类型Inner似乎不是泛型。)
如果您真的只想计算“本地”泛型类型参数并排除从其外部类型继承的参数,则可以简单地减去外部类型(type.DeclaringType)的泛型参数总数:
static int LocalGenericParameterCount(this Type t)
    => t.IsNested ? t.GenericParameterCount() - t.DeclaringType.GenericParameterCount()
                  : t.GenericParameterCount();

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