2011-05-12 139 views
1

免責聲明:理論問題

新的約束規定,在泛型類 聲明任何 類型參數必須有一個公共 參數構造函數。爲什麼new()約束需要公共構造函數?

來源:http://msdn.microsoft.com/en-us/library/sd2w2ew5(v=vs.80).aspx

如果我想我的泛型類有保護參數的構造函數呢?例如,如果我想寫一個Singleton類,我將其「附加」到其他類以使它們成爲Singleton,我不希望派生類可實例化 - 所有內容都應該通過.Instance屬性。

internal class Singleton<T> where T : new() 
{ 
    public static T Instance { get; private set; } 

    static Singleton() 
    { 
     Singleton<T>.Instance = new T(); 
    } 
} 

internal class OnlyOneOfMe : Singleton<OnlyOneOfMe> 
{ 
    protected OnlyOneOfMe() 
    { 
    } 
} 

這樣,Singleton<T>能夠創建OnlyOneOfMe類的唯一實例,但沒有什麼可以(除非它是一個子類)。

「如果通用父類可以訪問泛型類型的受保護成員呢?」

+7

如果構造函數被保護,你打算如何調用它? – 2011-05-12 20:37:27

+0

我知道它不被支持,但我的思考過程是:「如果派生類具有受保護的構造函數,那麼泛型類(父類)就可以看到它,因此它不需要公開,對不對?」 – 2011-05-12 20:44:18

+1

不,錯了。受保護只能在一個方向上工作。只有後代才能訪問受保護的構造函數,基類完全不知道它們。 – 2011-05-12 20:45:29

回答

1

如果構造函數被保護,Singleton將無法調用它。

而且即使我可以,我也會避免像那樣執行單例模式。這很麻煩 - 如果你想要一個從抽象類繼承的單例類呢?

4

因爲這是約束的定義。這有點像問爲什麼T : class要求T是引用類型。根據定義,這是真的。

此外,如果它不是公共構造函數,那麼約束的要點是什麼?如果它不是公共的,那麼接收類型參數T的類將無法調用構造函數。

+0

是的,我意識到「事情就是這樣。」我在問爲什麼它不能得到保護。 'T:class'根本不一樣。這個約束非常具體,因爲它必須是。 new()約束是過於具體的IMO,因爲泛型類能夠訪問派生類的受保護成員,包括它的構造函數。 – 2011-05-12 20:44:45

+0

@Josh M. Singleton將能夠訪問T上受保護的構造函數的唯一方法是,如果Singleton繼承自T - 在這種情況下,使用泛型沒有意義。 – reavowed 2011-05-12 20:54:00

+0

我知道,這更像是一個理論問題,我明白爲什麼它不能這樣工作。我躲過了「如果一個通用父類可以訪問泛型類型的受保護成員呢?」 – 2011-05-12 21:13:49

1

.NET不會知道你不想接受

class OnlyOneOfMe : Singleton<Other> 

爲有效類。由於它實際上是有效的,它會嘗試創建類並需要一個公共的其他構造函數。

2

您可以使用reflection調用受保護的構造函數。但是,這應該會引發警告信號,表明您正在做某些您不應該做的事情。在大多數情況下,您應該能夠避免使用單身人士,而應該使用dependency injection。如果這也不起作用,您可以使用類似環境上下文模式(see my answer here)。

相關問題