Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

c#-6.0

nameof

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.

like image 886
dlf Avatar asked Nov 19 '15 21:11

dlf


1 Answers

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.

like image 159
31eee384 Avatar answered Oct 31 '22 23:10

31eee384