c# - 来自类型参数的泛型类

标签 c# generics types

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

我有这样的东西:

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>();
    }
}

我想要的是从一个类型创建一个 GenericClass。例如:

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>泛型中的 s 由 C# 编译器在构建时 解析,并插入真实的类名。当您必须将其推迟到运行时时,您最终会付出性能代价。

关于c# - 来自类型参数的泛型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10317036/

相关文章:

c# - WPF MVVM : Set focus to current selected item in Datagrid on button click

c# - 将主音频音量的变化确定为事件(音量变化监听器)

c# - 一种将字符串排序为另一个字符串的更简洁的方法

c# - 按位置访问泛型类型的属性

java - 如何在Java中创建通用数组?

c# - 序列化泛型类

php - 我应该使用哪种 SQL 类型来输入值 4.865472349

c++ - 内存浪费?如果 main() 应该只返回 0 或 1,为什么 main 声明为 int 而不是 short int 甚至 char?

c# - WPF ViewModel 类中的调度程序

Haskell:I/O 和从函数返回