2008-08-04 101 views
33

我正在尋找一些方法來有效地隱藏繼承成員。我有一個從普通基類繼承的類庫。一些更新的後代類繼承了依賴性屬性,這些屬性已經變得殘缺不全,並且在使用智能感知或在視覺設計器中使用類時可能會有點混淆。隱藏繼承成員

這些類都是編寫爲WPF或Silverlight 2.0編譯的控件。我知道ICustomTypeDescriptorICustomPropertyProvider,但我很確定那些不能在Silverlight中使用。

它不像可用性問題那樣是一個功能問題。我該怎麼辦?

更新

一些我真的想隱藏來自不屬於我自己的,因爲特定的工具我設計了祖先的屬性,我不能做構件,隱藏new運營商。 (我知道,這是荒謬的)

回答

32

重寫他們像邁克爾:建議above並防止人們從使用重載方法,將它們標記爲過時:

[Obsolete("These are not supported in this class.", true)] 
public override void dontcallmeanymore() 
{ 
} 

如果第二個參數設置爲true,如果有人試圖調用該方法,並且第一個參數中的字符串是消息,則會生成編譯器錯誤。如果parm2爲false,則只會生成編譯器警告。

+0

你能不能封住它,同樣的效果呢? – 2017-01-19 16:51:57

+0

@詹姆斯沒有obselete真正的防止成員_access_,密封防止成員_inheritance_。所以一個密封的類不能被派生出來,並且一個密封的方法允許其他類成員被覆蓋,但是阻止該成員被覆蓋。密封不會阻止調用該類或成員,而如果嘗試調用它,則使用真正的obselete會拋出編譯器錯誤。 – 2017-05-25 15:31:26

16

雖然你不能阻止那些繼承成員,據我所知的使用情況,你應該能夠使用EditorBrowsableAttribute從智能感知隱藏起來:

Using System.ComponentModel; 

[EditorBrowsable(EditorBrowsableState.Never)] 
private string MyHiddenString = "Muahahahahahahahaha"; 

編輯:剛纔看到這在文檔註釋中,這使得它對於此目的有點沒用:

有一個突出的說明,指出該屬性「不禁止在同一個程序集中的類的成員」。這是事實,但不完整。實際上,該屬性不會在同一個解決方案中壓縮類的成員。

8

我認爲你最好最簡單的方法是考慮構成而不是繼承。或者,您可以創建一個包含您想要的成員的接口,讓您的派生類實現該接口,並根據接口進行編程。

13

你可以做的一件事是包含對象而不是從其他類擴展。這會給你提供最大的靈活性,但是如果你絕對需要這個類型的對象,它不是理想的解決方案(不過你可以從getter中暴露對象)。

這樣:

public class MyClass : BaseClass 
{ 
    // Your stuff here 
} 

變爲:

public class MyClass 
{ 
    private BaseClass baseClass; 

    public void ExposeThisMethod() 
    { 
     baseClass.ExposeThisMethod(); 
    } 
} 

或者:(?SP)

public class MyClass 
{ 
    private BaseClass baseClass; 

    public BaseClass BaseClass 
    { 
     get 
     { 
      return baseClass; 
     } 
    } 
} 
3

我知道這有幾個答案,現在已經很老了,但最簡單的方法是將其聲明爲new private

考慮一個我目前正在使用的示例,其中有一個API可用於第三方DLL中的每個方法。我必須採取他們的方法,但我想使用.Net屬性,而不是「getThisValue」和「setThisValue」方法。因此,我構建了第二個類,繼承第一個類,使用get和set方法創建一個屬性,然後將原始get和set方法重寫爲private。任何想要在它們上面構建不同的東西的人都可以使用它們,但是如果他們只是想使用我正在構建的引擎,那麼他們就可以使用屬性而不是方法。

使用雙類方法擺脫了無法使用new聲明來隱藏成員的任何限制。如果成員標記爲虛擬,則無法使用override

public class APIClass 
{ 
    private static const string DllName = "external.dll"; 

    [DllImport(DllName)] 
    public extern unsafe uint external_setSomething(int x, uint y); 

    [DllImport(DllName)] 
    public extern unsafe uint external_getSomething(int x, uint* y); 

    public enum valueEnum 
    { 
     On = 0x01000000; 
     Off = 0x00000000; 
     OnWithOptions = 0x01010000; 
     OffWithOptions = 0x00010000; 
    } 
} 

public class APIUsageClass : APIClass 
{ 
    public int Identifier; 
    private APIClass m_internalInstance = new APIClass(); 

    public valueEnum Something 
    { 
     get 
     { 
      unsafe 
      { 
       valueEnum y; 
       fixed (valueEnum* yPtr = &y) 
       { 
        m_internalInstance.external_getSomething(Identifier, yPtr); 
       } 
       return y; 
      } 
     } 
     set 
     { 
      m_internalInstance.external_setSomething(Identifier, value); 
     } 
    } 

    new private uint external_setSomething(int x, float y) { return 0; } 
    new private unsafe uint external_getSomething(int x, float* y) { return 0; } 
} 

現在valueEnum可用於兩個類,但只有該屬性在APIUsageClass類中可見。 APIClass類仍然適用於想要擴展原始API或以不同方式使用API​​的人,並且APIUsageClass適用於想要更簡單的用戶。

最終,我會做的是使APIClass內部,並只暴露我的繼承類。

1

我測試了所有建議的解決方案,並沒有真正隱藏新成員。

但這一個作用:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public new string MyHiddenProperty 
{ 
    get { return _myHiddenProperty; } 
} 

但在代碼behide它仍然是可訪問的,所以加以及過時的屬性

[Obsolete("This property is not supported in this class", true)] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public new string MyHiddenProperty 
{ 
    get { return _myHiddenProperty; } 
} 
3

要完全隱藏和標記不使用,包括智能感知它我相信是大多數讀者期望的...

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
0

您可以使用接口

public static void Main() 
    { 
     NoRemoveList<string> testList = ListFactory<string>.NewList(); 

     testList.Add(" this is ok "); 

     // not ok 
     //testList.RemoveAt(0); 
    } 

    public interface NoRemoveList<T> 
    { 
     T this[int index] { get; } 
     int Count { get; } 
     void Add(T item); 
    } 

    public class ListFactory<T> 
    { 
     private class HiddenList: List<T>, NoRemoveList<T> 
     { 
      // no access outside 
     } 

     public static NoRemoveList<T> NewList() 
     { 
      return new HiddenList(); 
     } 
    }