类型参数中的泛型类

本文关键字:泛型类 类型参数 | 更新日期: 2023-09-27 18:32:24

有没有办法从类型参数创建泛型类。

我有这样的东西:

public class SomeClass
{
    public Type TypeOfAnotherClass { get; set; }
}
public class OneMoreClass
{
}
public class GenericClass<T>
    where T : class
{
    public void DoNothing() {}
}
public class GenericClass
{
    public static GenericClass<T> GetInstance<T>(T ignored)
        where T : class
    {
        return new GenericClass<T>();
    }
}

我想要的是从一个类型创建一个泛型类。前任:

var SC = new SomeClass();
SC.TypeOfAnotherClass = typeof(OneMoreClass);
var generic = GenericClass.GetInstance(SC.TypeOfAnotherClass);
Assert.AreEqual(typeof(GenericClass<OneMoreClass>), generic.GetType());

在这里,我希望得到GenericClass<OneMoreClass>的实例,但我得到GenericClass<Type>

我还尝试使用该类型的实例。前任:

var generic = GenericClass.GetInstance(Activator.CreateInstance(SC.TypeOfAnotherClass));

这次我得到了GenericClass<object>

有没有办法完成这项任务?

类型参数中的泛型类

如果你在构建时知道你真正想要的类型(OneMoreClass),那么你应该使用它:

var generic = GenericClass.GetInstance<OneMoreClass>();

但我假设您在构建时不知道它,并且必须在运行时获取type。你可以通过反射来做到这一点,但它并不漂亮,而且速度很慢:

public class GenericClass
{
    public static object GetInstance(Type type)
    {
        var genericType = typeof(GenericClass<>).MakeGenericType(type);
        return Activator.CreateInstance(genericType);
    }
}

由于您在构建时不知道结果类型,因此除了从方法返回object(或dynamic)之外,无法返回任何内容。


这是慢多少(对于 100,000 个创建)

public class GenericClass
{
    public static object GetInstance(Type type)
    {
        var genericType = typeof(GenericClass<>).MakeGenericType(type);
        return Activator.CreateInstance(genericType);
    }
    public static GenericClass<T> GetInstance<T>()
        where T : class
    {
        return new GenericClass<T>();
    }
}
    [Test]
    public void CanMakeGenericViaReflection_ButItsSlow()
    {
        var timer = new Stopwatch();
        var SC = new SomeClass();
        SC.TypeOfAnotherClass = typeof(OneMoreClass);
        timer.Start();
        for (int x = 0; x < 100000; x++)
        {
            GenericClass.GetInstance(SC.TypeOfAnotherClass);
        }
        timer.Stop();
        Console.WriteLine("With Reflection: " + timer.ElapsedMilliseconds + "ms.");
        timer.Restart();
        for (int x = 0; x < 100000; x++)
        {
            GenericClass.GetInstance<OneMoreClass>();
        }
        timer.Stop();
        Console.WriteLine("Without Reflection: " + timer.ElapsedMilliseconds + "ms.");
    }

结果:

With Reflection: 243ms.
Without Reflection: 2ms.

所以慢了 100 多倍。

关于泛型,

真正需要注意的是,泛型中的<T>由 C# 编译器在生成时解析,并插入真实的类名。当您必须将其推迟到运行时时,您最终会付出性能代价。

我不确定你在这里问的到底是什么。如果我正确理解您,这就是您正在寻找的:

public class GenericClass
{
    public static GenericClass<T> GetInstance<T>(T ignored)
        where T : class
    {
        return new GenericClass<T>();
    }
    public static GenericClass<T> GetInstance<T>()
        where T : class
    {
        return new GenericClass<T>();
    }
}

用法:

  var generic1 = GenericClass.GetInstance<OneMoreClass>();
  var generic2 = GenericClass.GetInstance(new OneMoreClass());

断言:

Assert.AreEqual(typeof(GenericClass<OneMoreClass>), generic1.GetType());
Assert.AreEqual(typeof(GenericClass<OneMoreClass>), generic2.GetType());