代码之家  ›  专栏  ›  技术社区  ›  Matt

C中泛型的限制类型参数#

  •  2
  • Matt  · 技术社区  · 14 年前

    我可能会想象一些事情,但我似乎记得在Java中,我可以声明一个字段或参数如下:

    public class BarHandler{
    
        public Class<? extends Foo> fooType;
    
        public ProcessedBar Process(string xml){
            Foo foo = fooType.GetInstance();
            return foo.process(xml)
        }
    }
    

    这对于工厂样式的系统很有用,例如,您必须能够生成相关类型的新实例。

    我试图弄清楚C中是否存在类似的模拟,或者如果这可能是Java中可用的东西。

    4 回复  |  直到 13 年前
        1
  •  1
  •   Dr. Wily's Apprentice    14 年前

    下面是280Z28答案的变体。我已将“type”类重命名为“factory”,因为在我的版本中,它公开了 GetInstance 方法而不是 Value 类型的属性 Type . 这将使用2个泛型参数和泛型约束来强制类型类的原始应答构造函数中的规则。

    public abstract class Factory<T>
    {
        public abstract T GetInstance();
    }
    
    public sealed class IoCFactory<T, TDerived> : Factory<T>
        where TDerived : T // compiler enforces that TDerived derives from T
    {
        public override T GetInstance()
        {
            // TODO: retrieve instance of TDerived from IoC container such as Spring.NET, StructureMap, Unity, etc.
            throw new NotImplementedException();
        }
    }
    
    public sealed class ActivatorFactory<T, TDerived> : Factory<T>
        where TDerived : T, new() // compiler enforces that TDerived derives from T and that it has a parameterless constructor
    {
        public override T GetInstance()
        {
            return Activator.CreateInstance<TDerived>();
        }
    }
    
    public class BarHandler
    {
        public Factory<Foo> fooFactory { get; set; }
    
        public ProcessedBar Process(string xml)
        {
            Foo foo = fooFactory.GetInstance();
            return foo.Process(xml);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            BarHandler handler = new BarHandler();
    
            handler.fooFactory = new ActivatorFactory<Foo, Bar>();
    
            var processedResult = handler.Process("<bar>Yar!</bar>");
        }
    }
    
        2
  •  5
  •   Tim Cooper    13 年前

    是的,看到了 generic constraints . 与您的示例相同的是:

    public class SomeClass<T>
        where T : Foo
    {
        private T fooType;
    }
    

    编辑后编辑:我相信你指的是 wildcards ,在这种情况下,您应该阅读 covariance and contravariance 关于仿制药。

        3
  •  1
  •   TreDubZedd    14 年前
    public class GenericClass<T> where T : Foo
    
        4
  •  1
  •   Sam Harwell    14 年前

    您可以使用一个非常简单的包装器来进行此注释和一个便宜的运行时检查:

    public sealed class Type<T>
    {
        public Type(Type type)
        {
            if (type == null)
                throw new ArgumentNullException("type");
            if (!typeof(T).IsAssignableFrom(type))
                throw new ArgumentException(string.Format("The specified type must be assignable to '{0}'.", typeof(T).FullName));
    
            this.Value = type;
        }
    
        public Type Value
        {
            get;
            private set;
        }
    }
    

    使用 Activator.CreateInstance 实际创建类型的实例。假设 FooDerived 来源于 Foo .

    Type<Foo> fooType = new Type<Foo>(typeof(FooDerived));
    Activator.CreateInstance(fooType.Value);