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

非泛型类中是否支持泛型构造函数?

  •  40
  • greenoldman  · 技术社区  · 14 年前

    是不是不支持,是不是支持但我要做一些技巧?

    class Foo
    {
      public Foo<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
      {
         ...
      }
    }
    

    备注

    3 回复  |  直到 14 年前
        1
  •  82
  •   Jon Skeet    14 年前

    不,泛型或非泛型类都不支持泛型构造函数。同样,不支持泛型事件、属性和终结器。

    只是偶尔我同意它会很方便-但是语法看起来很糟糕。例如,假设您有:

    public class Foo<T> {}
    
    public class Foo
    {
        public Foo<T>() {}
    }
    

    你会怎么做

    new Foo<string>()
    

    你知道吗?调用非泛型类的泛型构造函数,还是泛型类的普通构造函数?你必须以某种方式区分它们,这会很混乱:(

    同样,考虑泛型类中的泛型构造函数:

    public class Foo<TClass>
    {
        public Foo<TConstructor>() {}
    }
    

    如何调用构造函数?希望我们都能同意:

    new Foo<string><int>()
    

    太可怕了。。。

    因此,是的,从语义上说,它偶尔会有用——但不幸的是,由此产生的丑陋抵消了这一点。

        2
  •  31
  •   kdbanman    9 年前

    不支持泛型构造函数,但您可以通过定义泛型, static 方法返回一个新的 Foo :

    class Foo
    {
      public static Foo CreateFromFuncs<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
      {
         ...
      }
    }
    

    用法如下:

    // create generic dependencies
    var func1 = new Func<byte, string>(...);
    var func2 = new Func<string, byte>(...);
    
    // create nongeneric Foo from dependencies
    Foo myFoo = Foo.CreateFromFuncs<byte, string>(func1, func2);
    
        3
  •  0
  •   Earth Engine    10 年前

    下面是一个实际的例子,说明如何使用额外的构造函数类型参数以及解决方法。

    我要介绍一个简单的 RefCounted 包装器 IDisposable :

    public class RefCounted<T> where T : IDisposable
    {
        public RefCounted(T value)
        {
            innerValue = value;
            refCount = 1;
        }
    
        public void AddRef()
        {
            Interlocked.Increment(ref refCount);
        }
    
        public void Dispose()
        {
            if(InterlockedDecrement(ref refCount)<=0)
                innerValue.Dispose();
        }
    
        private int refCount;
        private readonly innerValue;
    }
    

    RefCounted<Control> RefCounted<Button> 同时保持两个对象引用计数,即仅当两个实例都被释放以释放基础对象时。

    最好的方法是你能写(就像C++人能做的那样)

    public RefCounted(RefCounted<U> other)
    {
        ...whatever...
    }
    

    private readonly Func<T> valueProvider;
    private readonly Action disposer;
    
    private RefCounted(Func<T> value_provider, Action disposer)
    {
        this.valueProvider = value_provider;
        this.disposer = disposer;
    }
    
    public RefCounted(T value) : this(() => value, value.Dispose)
    {
    }
    
    public RefCounted<U> Cast<U>() where U : T 
    {
        AddRef();
        return new RefCounted<U>(() => (U)(valueProvider()),this.Dispose);
    }
    
    public void Dispose(){
        if(InterlockedDecrement(ref refCount)<=0)
            disposer();
    }
    

    如果您的类有任何泛型类型的字段,那么您别无选择,只能将所有这些类型放到类中。但是,如果您只是想对构造函数隐藏某些类型,则需要使用上述技巧—使用隐藏的构造函数将所有内容组合在一起,并定义一个普通的泛型函数来调用该构造函数。