在不指定类型参数的情况下对泛型 class 的成员使用 nameof

Use nameof on a member of a generic class without specifying type arguments

class Foo<T>
{
   public T Bar() { /* ... */ }
}

我想把 Bar 的名字传给 Type.GetMethod(string)。我可以用 someType.GetMethod(nameof(Foo<int>.Bar)) 来做到这一点,但是 int 在这里完全是任意的;有什么办法可以省略吗?遗憾的是,nameof(Foo<>.Bar) 不起作用。

在这个玩具箱中这没什么大不了的,但如果有多个类型参数,尤其是如果它们附加了 where 约束,将它们拼写出来可能会成为一项任务。

nameof documentation 明确表示你想做的事情是不允许的,不幸的是:

Because the argument needs to be an expression syntactically, there are many things disallowed that are not useful to list. The following are worth mentioning that produce errors: predefined types (for example, int or void), nullable types (Point?), array types (Customer[,]), pointer types (Buffer*), qualified alias (A::B), and unbound generic types (Dictionary<,>), preprocessing symbols (DEBUG), and labels (loop:).

您可能做的最好的事情是在界面中指定 Bar,然后使用 nameof(IFoo.Bar)。当然,如果 Bar 在其签名中包含与 T 相关的内容(例如在这种特定情况下),则这不是一个选项。


另一种选择是创建一个界面,其中每个 T 都替换为 object。然后具体类型显式实现接口,同时实现相同方法的泛型版本。

这有一些缺点:

  • 更大的API表面
  • 更困难和容易出错的重构
  • 失去编译时类型安全,因为调用者可能使用 object 接口。

仅使用 nameof 这可能是不合理的,但在某些情况下,由于其他原因,此策略是有意义的。在那些情况下,能够使用 nameof 只是一个方便的奖励。