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

1

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

I'd like to pass Bar's name to Type.GetMethod(string). I can do this as someType.GetMethod(nameof(Foo<int>.Bar)), but that int is wholly arbitrary here; is there any way I can omit it? Sadly, nameof(Foo<>.Bar) doesn't work.

It's not such a big deal in this toy case, but if there are multiple type parameters and especially if they have where constraints attached to them, spelling them all out can become a task.

Subdebutante answered 19/11, 2015 at 21:58 Comment(0)
D
6

The nameof documentation specifically says that what you want to do is disallowed, unfortunately:

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:).

The best you can probably do is specify Bar in an interface, and use nameof(IFoo.Bar). Of course, that isn't an option if Bar includes something related to T in its signature (like in this specific case).


Another option is to create an interface where each T is replaced with object. Then the concrete type implements the interface explicitly, also implementing generic versions of the same methods.

This has a few downsides:

  • Larger API surface
  • More difficult and error-prone refactoring
  • Losing compile-time type safety because a caller might use the object interface.

This probably isn't justifiable just to use nameof, but in some cases this strategy makes sense for other reasons. In those cases, being able to use nameof would just be a convenient bonus.

Detta answered 19/11, 2015 at 22:8 Comment(3)
"for example if Bar includes something related to T in its signature" which is exactly the case for me (edited the question to include this). Ah well.Subdebutante
For this case, anyway, I'd rather just enter some unnecessary type arguments. For one thing, having both T and object versions of Bar would leave the code vulnerable to the same sort of post-renaming bugs that nameof was introduced to solve in the first place. If I were prepared to tolerate that, it would be simpler just to do GetMethod("Bar"). Life goes on. :)Subdebutante
@Subdebutante Agreed. Moved contents of my comment into the answer for posterity.Detta

© 2022 - 2024 — McMap. All rights reserved.