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

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

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

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

1 ответ

Решение

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

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

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


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

Это имеет несколько недостатков:

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

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

Другие вопросы по тегам