Установка универсального типа во времени выполнения

У меня есть класс

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'
25
задан Venkat Peri 9 April 2010 в 02:33
поделиться

5 ответов

Вы не можете. Идентификаторы универсального типа должны быть известны во время компиляции.

edit

Как и в других сообщениях, это возможно, если динамически генерировать метод и вызывать его, что, конечно, несет в себе опасность. См. Сообщения Томаса и Дафана для получения дополнительной информации.

10
ответ дан 28 November 2019 в 20:47
поделиться

Вы не можете сделать это напрямую, но вы можете использовать отражение, чтобы предоставить параметр типа класса во время выполнения. Я не тестировал это, но что-то вроде этого должно сработать:

// 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;
}

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

29
ответ дан 28 November 2019 в 20:47
поделиться

Это абсолютно поддерживается во фреймворке и в 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);
    }
10
ответ дан 28 November 2019 в 20:47
поделиться

Вы не можете. Но вы задали неправильный вопрос для предоставленного случая. В этом случае (как и в 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 на количество предложений будет намного выше.

1
ответ дан 28 November 2019 в 20:47
поделиться

Попытка заменить параметр типа во время выполнения приведет к нарушению всей цели безопасности типов, которая обеспечивается компилятором C#. Компилятор C# следит за тем, чтобы параметр типа был указан во время компиляции и не было двусмысленности в аргументах типа во время выполнения. Я сомневаюсь, что вы можете заменить параметр типа во время выполнения в Generic Type. Указание аргумента типа типа "Type" почти как наличие несвязанного общего типа.

0
ответ дан 28 November 2019 в 20:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: