在运行时设置泛型类型

Ven*_*eri 25 c# generics

我上课了

public class A<T>
{
   public static string B(T obj)
   {
       return TransformThisObjectToAString(obj);
   }
}
Run Code Online (Sandbox Code Playgroud)

上面使用字符串纯粹是示范性的.我可以在已知/指定的类型上调用这样的静态函数:

string s= A<KnownType>.B(objectOfKnownType);
Run Code Online (Sandbox Code Playgroud)

如果我事先不知道T,我该怎么做这个调用,而是我有一个Type类型的变量来保存类型.如果我这样做:

Type t= typeof(string);
string s= A<t>.B(someStringObject);
Run Code Online (Sandbox Code Playgroud)

我得到这个编译器错误:

Cannot implicitly convert type 't' to 'object'
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 29

您无法直接执行此操作,但可以使用反射在运行时提供类的类型参数.我没有测试过这个,但这样的事情应该有效:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

当然,问题是这是否真的是你需要的 - 如果你对作为参数给出的对象一无所知,你也可以用对象编写整个代码.但是,我可以想象一些有用的场景,所以我想你可以尝试使用它.


Fem*_*ref 10

你不能.通用类型标识符必须在编译时知道.

编辑

从其他帖子来看,似乎可以通过动态生成方法并调用它 - 当然这有危险.有关更多信息,请参阅Thomas'和Dathan的帖子.

  • 更准确地说,没有静态类型的方法可以做到这一点; 或者也许没有惯用的方式.但是,正如Tomas和我的回复所示,该方法可以动态解析,并在运行时使用任意参数调用. (3认同)

Dat*_*han 10

在框架和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);
    }
Run Code Online (Sandbox Code Playgroud)