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

时间:2010-08-31 07:35:21

标签: c# generics constructor

是否不支持,是否支持,但我必须做一些技巧?

示例:

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

泛型仅用于构造函数,没有依赖于它们的字段/属性,我使用它(泛型)来强制执行f1和f2的类型相关。

备注:我找到了解决方法 - 静态方法创建,但无论如何我很好奇为什么我有直接方法的问题。

3 个答案:

答案 0 :(得分:65)

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

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

public class Foo<T> {}

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

会是什么

new Foo<string>()

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

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

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

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

new Foo<string><int>()

非常可怕......

所以是的,在语义上它偶尔会有用 - 但不幸的是,由此产生的丑陋抵消了这种情况。

答案 1 :(得分:21)

不支持通用构造函数,但您可以通过简单地定义返回新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);

答案 2 :(得分:0)

这是一个关于如何获得额外构造函数类型参数的实用示例,以及解决方法。

我将为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...
}

但是C#不允许这样做。所以解决方案是使用一些间接。

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

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