2010-04-29 87 views
11

有沒有辦法限制C#中嵌套類的實例化?我想防止嵌套類從除嵌套類以外的任何其他類實例化,但要允許從其他代碼完全訪問嵌套類。嵌套類構造函數的可見性

+0

聽起來像你在重塑Singleton設計模式。 – 2010-04-29 11:30:12

+0

@Bastiaan:你的意思是「執行」。您不重新設計設計模式.... – James 2010-04-29 11:37:40

+0

聲明您不想被訪問的成員,包括構造函數,內部成員。這是默認設置。 – 2010-04-29 13:08:01

回答

27

通常我爲您想要暴露給其他類的功能創建一個接口,然後使嵌套類爲私有並實現該接口。這樣嵌套的類定義可以隱藏:

public class Outer 
{ 
    private class Nested : IFace 
    { 
     public Nested(...) 
     { 
     } 
     //interface member implementations... 
    } 

    public IFace GetNested() 
    { 
     return new Nested(); 
    } 
} 
6

總之,不,你不能這樣做。有一個accessibity修飾符「公共」,意思是「可以通過我內部或外部的任何東西訪問」,並且有一個可訪問性修飾符「private」,意思是「可以通過我內部的任何東西訪問」。沒有修飾符,意思是「可以在我之外直接訪問它,但不能訪問它之外的任何東西」,這就是你需要將構造函數標記爲的東西。這根本不是一個類型系統思想的設計者會有用的概念。

你能描述一下爲什麼你想要這種瘋狂的可訪問性?也許有更好的方法來獲得你想要的東西。

+1

關閉我的頭頂(因爲這是我的擔憂):實現IAsyncResult。 – 2011-02-08 21:05:11

+0

錯誤,請參閱我的答案。 – MatteoSp 2013-11-05 14:34:38

+6

@MatteoSp:雖然我覺得你覺得我對我實現的功能有錯,但我覺得很愉快,但我向你保證,我認爲沒有適合描述原始海報的描述的可訪問性修飾符是正確的。 – 2013-11-05 16:05:42

-1

更新:不正確的答案,看評論

內部修改是你在找什麼:

public class OuterClass 
{ 
    public class NestedClass { 
     internal NestedClass() 
     { 

     } 
    } 
} 

NestedClass將是大家有目共睹的,但它的構造函數將只提供給在OuterClass。

+2

這個回答是錯誤的。如果你有'class ThirdClass {void M(){var x = new OuterClass.NestedClass(); }}。請記住,原始海報希望「*我想阻止嵌套類從除嵌套類以外的任何其他類實例化。」,顯然這不符合法案。 – 2013-11-05 16:00:54

+0

是的......你說得對。我沒有注意到我試圖從不同的程序集調用構造函數,這就是爲什麼內部修飾符正在工作... – MatteoSp 2013-11-05 20:49:29

3

由於C#語法中沒有任何東西,所以您必須實現諸如它們之間的「合約」之類的東西。你可以採取的事實,即嵌套類可以訪問其父的私有字段:

public class ParentClass 
{ 
    private static Func<FriendClass> _friendContract; 

    public class FriendClass 
    { 
     static FriendClass() 
     { 
      _friendContract=() => new FriendClass(); 
     } 

     private FriendClass() { } 
    } 

    ///Usage 
    public FriendClass MethodUse() 
    { 
     var fInstance = _friendContract(); 
     //fInstance.DoSomething(); 
     return fInstance; 
    } 
} 

當然,你可以調整合同來處理不同的參數

private static Func<Arg1,Arg2,FriendClass> _friendContract; 
+0

對我來說內部類的靜態構造函數不會被調用,而我得到一個nullreferenceexception – 2017-09-16 15:37:53

4

如果您需要滿足一個以下要求:

  • 你想嵌套類被密封,
  • 你不想複製所有嵌套類的併購ethod簽名就像Lee's answer接口,

我發現類似the one posted by ak99372一個解決方案,但沒有使用靜態初始化:

public class Outer 
{ 
    private interface IPrivateFactory<T> 
    { 
     T CreateInstance(); 
    } 

    public sealed class Nested 
    { 
     private Nested() { 
      // private constructor, accessible only to the class Factory. 
     } 

     public class Factory : IPrivateFactory<Nested> 
     { 
      Nested IPrivateFactory<Nested>.CreateInstance() { return new Nested(); } 
     } 
    } 

    public Nested GetNested() { 
     // We couldn't write these lines outside of the `Outer` class. 
     IPrivateFactory<Nested> factory = new Nested.Factory(); 
     return factory.CreateInstance(); 
    } 
} 

的想法是,Nested類的構造函數只能訪問到Factory類,它嵌套更深一層。 Factory類明確實現了專用接口IPrivateFactory的方法CreateInstance,以便只有看到IPrivateFactory的人才能調用CreateInstance並獲得Nested的新實例。

守則Outer類不能自由創建的Nested情況下,不問Outer.GetNested()之外,因爲

  1. Outer.Nested的構造是民營化,所以他們不能把它直接
  2. Outer.Nested.Factory可以被實例化,但不能投到IPrivateFactory,所以它的CreateInstance()方法不能被調用。

請注意,我不會建議在生產代碼中大量使用該模式,但這是一種在極少數情況下使用我的套筒的技巧。

1

對於Joshua Smith提出的答案,我發現有必要強制FriendClass的靜態構造函數運行,通過從ParentClass的靜態構造函數調用FriendClass上的靜態Initalize()方法實現。

+0

您應該評論約書亞的回答,而不是發佈一個不是真正的答案。 – 2016-04-27 12:00:47

0
public class Outer 
{ 
    public class Nested 
    { 
     readonly Outer Outer; 

     public Nested(Outer outer /* , parameters */) 
     { 
      Outer = outer; 

      // implementation 
     } 

     // implementation 
    } 

    public Nested GetNested(/* parameters */) => new Nested(this /* , parameters */); 
} 

請注意,您可以從嵌套訪問Outer的私有成員。