Можете ли вы использовать методы generics в С#, если тип неизвестен до выполнения?
Самый простой способ объяснить, что я имею в виду, с образцом кода. Это не компилируется, но есть ли способ достичь этого эффекта:
foreach(Type someType in listOfTypes)
{
SomeMethod<someType>();
}
Было бы очень удобно, если бы это сработало, но это не так. Есть ли другой способ достичь того же, что и выше, и почему С# не разрешает это быть юридическим выражением?
Edit: Похоже, что единственный способ сделать это - это отражение, которое может быть слишком медленным для наших нужд. Любое понимание того, почему нет эффективного способа встраивания, и работает ли что-то подобное в С# 4.0?
Ответы
Ответ 1
Вы можете использовать отражение. Предполагая, что текущий объект содержит метод SomeMethod()
, код для этого будет выглядеть так:
GetType().GetMethod("SomeMethod").
MakeGenericMethod(new Type[] { someType }).Invoke(this, null);
Обратите внимание, что если SomeMethod()
не является общедоступным, ваш код может не выполняться в средах с более низким доверием.
Ответ 2
Почему С# не разрешает это быть юридическим выражением?
Как отмечали другие, вы не можете этого сделать. Почему нет? Ну, рассмотрим ваш пример:
foreach(Type someType in listOfTypes)
{
SomeMethod<someType>();
}
Обратите внимание, что каждый тип в списке типов не может быть известен до выполнения, тогда как параметр типа SomeMethod
должен быть известен во время компиляции. Компилятор не может сообщить, к какому SomeMethod<T>
разрешить ваш вызов, поэтому это незаконно.
В С# 4 это и многие другие подобные вещи будут возможны с включением DLR в CLR. В частности, вызов динамического метода позволит вам вызывать методы, которые могут быть неизвестны во время компиляции.
Ответ 3
Единственный способ сделать это сегодня - через отражение. См. MethodInfo.MakeGenericMethod(Тип []).