2010-08-31 139 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(); 
} 

如果你的類有任何泛型類型的字段,你別無選擇,只能將所有類型都放到類中。然而,如果你只想從構造函數中隱藏某種類型,你將需要使用上述技巧 - 使用隱藏的構造函數將所有內容放在一起,並定義一個普通的泛型函數來調用構造函數。