Используйте nameof для члена универсального класса без указания аргументов типа

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

Я хочу передать имя Бара Type.GetMethod(string). Я могу сделать это как someType.GetMethod(nameof(Foo<int>.Bar)), но int здесь совершенно произвольно; есть ли способ, которым я могу опустить это? К сожалению, nameof(Foo<>.Bar) не работает.

В этом игрушечном случае это не такая уж большая проблема, но если есть несколько параметров типа и особенно если к ним прикреплены where ограничений, то их расшифровка может стать задачей.


person dlf    schedule 19.11.2015    source источник


Ответы (1)


В nameof документации конкретно сказано, что то, что вы хотите сделать, к сожалению, запрещено. :

Поскольку синтаксически аргумент должен быть выражением, есть много запрещенных вещей, которые бесполезно перечислять. Следует упомянуть следующее, вызывающее ошибки: предопределенные типы (например, int или void), типы, допускающие значение NULL (Point?), типы массивов (Customer[,]), типы указателей (Buffer*), квалифицированные псевдонимы (A::B) и непривязанные универсальные типы. типы (Dictionary<,>), символы предварительной обработки (DEBUG) и метки (loop:).

Лучшее, что вы можете сделать, это указать Bar в интерфейсе и использовать nameof(IFoo.Bar). Конечно, это не вариант, если Bar включает в свою подпись что-то, связанное с T (как в этом конкретном случае).


Другой вариант — создать интерфейс, в котором каждое T заменено на object. Затем конкретный тип явно реализует интерфейс, а также реализует универсальные версии тех же методов.

У этого есть несколько недостатков:

  • Увеличенная поверхность API
  • Более сложный и подверженный ошибкам рефакторинг
  • Потеря безопасности типа во время компиляции, потому что вызывающая сторона может использовать интерфейс object.

Это, вероятно, не оправдано только для использования nameof, но в некоторых случаях эта стратегия имеет смысл по другим причинам. В таких случаях возможность использовать nameof будет просто удобным бонусом.

person 31eee384    schedule 19.11.2015
comment
например, если Bar включает в свою подпись что-то, связанное с T, что как раз для меня (отредактировал вопрос, чтобы включить это). Ах хорошо. - person dlf; 20.11.2015
comment
Во всяком случае, в этом случае я бы предпочел просто ввести несколько ненужных аргументов типа. Во-первых, наличие как T, так и object версии Bar сделало бы код уязвимым для тех же ошибок после переименования, для решения которых изначально была введена nameof. Если бы я был готов это терпеть, было бы проще просто сделать GetMethod("Bar"). Жизнь продолжается. :) - person dlf; 20.11.2015
comment
@dlf Согласен. Переместил содержимое моего комментария в ответ для потомков. - person 31eee384; 20.11.2015