Используйте 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
будет просто удобным бонусом.