2010-08-31 141 views
36

不支持,是否支持,但我必须做一些技巧?是否支持非泛型类中的泛型构造函数?

实施例:

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

泛型仅在构造函数中使用,不存在字段/属性依赖于它们,我使用它(泛型)执行为f1和f2的类型的相关性。

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

回答

58

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

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

public class Foo<T> {} 

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

什么会

new Foo<string>() 

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

同样,考虑通用构造泛型类:

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

你将如何调用构造函数希望我们都可以同意:

new Foo<string><int>() 

是非常可怕的......

所以,是的,语义这将是很有用 - 但由此产生的丑陋抵消的是,很遗憾。

+0

你可以通过不允许泛型和非泛型类具有相同名称(严格来说,C#是否允许这样做?)来解决同名类问题。对于泛型类的泛型构造函数,我不认为它太可怕 - 它只是更高阶的泛型。 – 2010-08-31 07:46:26

+2

一种说法 - 泛型类中的构造函数是泛型的,因为类是通用的。然而(回答你的答案)它不能指定**额外的**通用参数。非常感谢你举例说明! – greenoldman 2010-08-31 07:50:41

+1

@Peter:不,同名的类问题不是问题,因为尽管你可以通过类型arity来“重载”类,但是没有任何歧义。查看'Tuple'就是一个例子。 – 2010-08-31 07:52:04

15

通用构造不支持,但你可以通过简单地定义一个通用的,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); 
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(); 
} 

如果你的类有任何泛型类型的字段,你别无选择,只能将所有类型都放到类中。然而,如果你只想从构造函数中隐藏某种类型,你将需要使用上述技巧 - 使用隐藏的构造函数将所有内容放在一起,并定义一个普通的泛型函数来调用构造函数。