У меня есть класс
public class A<T>
{
public static string B(T obj)
{
return TransformThisObjectToAString(obj);
}
}
Использование строки выше является чисто образцовым. Я могу вызвать статическую функцию как это очень хорошо на, знать/указывать тип:
string s= A<KnownType>.B(objectOfKnownType);
Как я выполняю этот вызов, если я не знаю T заранее, скорее у меня есть переменная Типа типа, который содержит тип. Если я делаю это:
Type t= typeof(string);
string s= A<t>.B(someStringObject);
Я получаю эту ошибку компилятора:
Cannot implicitly convert type 't' to 'object'
Вы не можете. Идентификаторы универсального типа должны быть известны во время компиляции.
edit
Как и в других сообщениях, это возможно, если динамически генерировать метод и вызывать его, что, конечно, несет в себе опасность. См. Сообщения Томаса и Дафана для получения дополнительной информации.
Вы не можете сделать это напрямую, но вы можете использовать отражение, чтобы предоставить параметр типа класса во время выполнения. Я не тестировал это, но что-то вроде этого должно сработать:
// We want to do something like this:
// object o = "Hello"
// Type t = o.GetType();
//
// This is pseudo-code only:
// string s = A<t>.B(o);
string InvokeA(object o) {
// Specify the type parameter of the A<> type
Type genericType = typeof(A<>).MakeGenericType(new Type[] { o.GetType() });
// Get the 'B' method and invoke it:
object res = genericType.GetMethod("B").Invoke(new object[] { o });
// Convert the result to string & return it
return (string)res;
}
Конечно, вопрос в том, действительно ли это то, что вам нужно - если вы ничего не знаете об объекте, указанном в качестве аргумента, вы также можете напишите весь код, просто используя объект. Тем не менее, я могу представить несколько сценариев, в которых это было бы полезно, поэтому я думаю, вы можете попробовать это использовать.
Это абсолютно поддерживается во фреймворке и в CLR, но в C # это не изящно. Однако вы можете выполнить то, что, как я думаю, вам нужно, с помощью вспомогательного метода:
public class A<T>
{
public static string B(T obj)
{
return obj.ToString();
}
}
public class MyClass
{
public static void DoExample()
{
Console.WriteLine(ExecuteB("Hi"));
Console.WriteLine(ExecuteB(DateTime.Now));
}
public static object ExecuteB(object arg)
{
Type arg_type = arg.GetType();
Type class_type = typeof(MyClass);
MethodInfo mi = class_type.GetMethod("ExecuteBGeneric", BindingFlags.Static | BindingFlags.Public);
MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { arg_type });
return mi2.Invoke(null, new object[] { arg });
}
public static object ExecuteBGeneric<T>(T arg)
{
return A<T>.B(arg);
}
Вы не можете. Но вы задали неправильный вопрос для предоставленного случая. В этом случае (как и в 99% случаев) все, что вам действительно нужно, - это ограничение типа .
Попробуйте:
public class A<T> where T : object
или, если T - известный класс, подкласс или интерфейс, тогда было бы лучше использовать
public class A<T> where T : YourAbstractClass
Существуют и другие ограничения типа. Подробнее: http://msdn.microsoft.com/en-us/library/d5x73970 (VS.80) .aspx
В общем, при изучении нового языка вам часто приходится мыслить широко. о том, чего вы хотите достичь , а не конкретно найти то, что вы хотите сделать . Это очень похоже на вербальные языки реального мира. В этом разница между изучением немецкого языка путем чтения словаря и принуждением слов к английскому синтаксису или изучением синтаксиса и подбором слов. Да, говорящий по-немецки поймет того, кто говорит не по словарю, но WTF на количество предложений будет намного выше.
Попытка заменить параметр типа во время выполнения приведет к нарушению всей цели безопасности типов, которая обеспечивается компилятором C#. Компилятор C# следит за тем, чтобы параметр типа был указан во время компиляции и не было двусмысленности в аргументах типа во время выполнения. Я сомневаюсь, что вы можете заменить параметр типа во время выполнения в Generic Type. Указание аргумента типа типа "Type" почти как наличие несвязанного общего типа.