【问题标题】:Chose generic implementation if the type parameter is struct or class如果类型参数是 struct 或 class,则选择泛型实现
【发布时间】:2015-12-22 10:35:37
【问题描述】:

我想以一种有效的方式实现我的通用 IQueue<T> 接口,如果 T 是 struct 则执行一个实现,如果 T 是一个类则执行另一个实现。

interface IQueue<T> { ... }

class StructQueue<T> : IQueue<T> where T : struct { ... }

class RefQueue<T> : IQueue<T> where T : class { ... }

我想要一个工厂方法,它基于 T 的种类返回一个或另一个实例:

static IQueue<T> CreateQueue<T>() {
    if (typeof(T).IsValueType) {
        return new StructQueue<T>();
    }
    return new RefQueue<T>();
}

当然,编译器指出 T 应该分别是不可空/可空类型参数。

有没有办法将 T 转换为结构类型(以及类类型)以使方法编译?这种运行时调度甚至可以用 C# 实现吗?

【问题讨论】:

  • 你可以使用反射
  • 请注意,可空值类型不通过 class 和 struct 约束。对于这种情况,您应该有第三个实现类。

标签: c# generics


【解决方案1】:

您可以使用Reflection 这样做:

static IQueue<T> CreateQueue<T>()
{
    if (typeof(T).IsValueType)
    {
        return (IQueue<T>)Activator
            .CreateInstance(typeof(StructQueue<>).MakeGenericType(typeof(T)));
    }

    return (IQueue<T>)Activator
        .CreateInstance(typeof(RefQueue<>).MakeGenericType(typeof(T)));
}

此代码使用Activator.CreateInstance method 在运行时创建队列。此方法接受您要创建的对象的类型。

要创建一个表示泛型类的Type,此代码使用MakeGenericType method 从开放的泛型类型(如StructQueue&lt;&gt;)创建一个封闭的泛型Type 对象。

【讨论】:

    【解决方案2】:

    Yacoub Massad 的回答是正确的,但是稍作修改,您就不需要为每次调用 CreateQueue 运行 MakeGenericType。

    下面的代码对每种类型运行一次 MakeGenericType,因为每种类型的QueueFactory&lt;T&gt; 都存在一个单独的静态变量,即QueueFactory&lt;int&gt;.queueType 将得到StructQueue&lt;int&gt;,而QueueFactory&lt;string&gt;.queueType 将得到RefQueue&lt;int&gt;

    public class QueueFactory<T>
    {
        static Type queueType = typeof(T).IsValueType ?
             typeof(StructQueue<>).MakeGenericType(typeof(T)) : typeof(RefQueue<>).MakeGenericType(typeof(T));
    
        public static IQueue<T> CreateQueue()
        {
            return (IQueue<T>)Activator.CreateInstance(queueType);
        }
    }
    

    在我的半科学测试中,它在大约十分之一的时间内创建了 100 万个实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      • 2018-01-02
      • 1970-01-01
      相关资源
      最近更新 更多