2015-12-21 45 views
5

如果T是struct,则我想通过执行一个实现来实现我的通用IQueue<T>接口,而如果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转换为struct类型(以及类类型)以使该方法编译?这种运行时调度甚至可以用C#进行吗?

+0

您可以使用Reflection –

+1

请注意,可为空的值类型不会传递,也不会传递'class',也不会传递'struct'约束。你应该有第三个这个案例的实施课。 – PetSerAl

回答

5

您可以使用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<>创建闭合通用Type对象。

1

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

下面的代码运行MakeGenericType每种类型的一次,因为一个单独的静态变量存在于每一个类型的QueueFactory<T>,即QueueFactory<int>.queueType将得到StructQueue<int>,而QueueFactory<string>.queueType会得到RefQueue<int>

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万个实例。

+0

谢谢,我对性能也有点担心。 – akarnokd