Hiding membres hérités

voix
34

Je cherche un moyen de cacher efficacement membres hérités. J'ai une bibliothèque de classes qui héritent des classes de base communs. Certaines des classes descendantes plus récentes héritent des propriétés de dépendance qui sont devenues vestigiale et peut être un peu déroutant lorsque vous utilisez IntelliSense ou en utilisant les classes dans un concepteur visuel.

Ces classes sont tous les contrôles qui sont écrits pour être compilé soit pour WPF ou Silverlight 2.0. Je sais ICustomTypeDescriptoret ICustomPropertyProvider, mais je suis certain ceux qui ne peuvent être utilisés dans Silverlight.

Ce n'est pas autant une question fonctionnelle comme un problème de convivialité. Que devrais-je faire?

Mettre à jour

Certaines des propriétés que je voudrais vraiment cacher viennent d'ancêtres qui ne sont pas moi - même et à cause d'un outil spécifique pour la conception que je suis, je ne peux pas cacher membre avec l' newopérateur. (Je sais, c'est ridicule)

Créé 04/08/2008 à 20:13
source utilisateur
Dans d'autres langues...                            


8 réponses

voix
32

Les remplacer comme Michael Suggère ci - dessus et pour empêcher les gens d'utiliser les méthodes surchargées, à marquer comme obsolète (sp?):

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

Si le second est parm la valeur true, une erreur de compilation sera générée si quelqu'un essaie d'appeler cette méthode et la chaîne dans la première parm est le message. Si param2 est faux qu'un avertissement du compilateur sera généré.

Créé 04/08/2008 à 21:14
source utilisateur

voix
16

Alors que vous ne pouvez pas empêcher l' utilisation de ces membres hérités à ma connaissance, vous devriez être en mesure de les cacher à l' aide de l'IntelliSense EditorBrowsableAttribute :

Using System.ComponentModel;

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

Edit: Je viens de voir cela dans les commentaires de la documentation, ce qui le rend un peu inutile à cet effet:

Il y a une note importante qui indique que cet attribut « ne supprime pas les membres d'une classe dans le même ensemble ». Cela est vrai, mais pas complète. En fait, l'attribut ne supprime pas les membres d'une classe dans la même solution.

Créé 04/08/2008 à 20:19
source utilisateur

voix
13

Une chose potentiel que vous pouvez faire est contenir l'objet plutôt que de s'étendre de l'autre classe. Cela vous donnera la plus grande flexibilité en termes d'exposer ce que vous voulez exposer, mais si vous avez absolument besoin de l'objet à être de ce type, il n'est pas la solution idéale (mais vous risquez d'exposer l'objet d'un getter).

Ainsi:

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

Devient:

public class MyClass
{
    private BaseClass baseClass;

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

Ou:

public class MyClass
{
    private BaseClass baseClass;

    public BaseClass BaseClass
    {
        get
        {
            return baseClass;
        }
    }
}
Créé 04/08/2008 à 20:22
source utilisateur

voix
8

Je pense que vous êtes le meilleur moyen est de moins hackish composition par opposition à considérer l'héritage.

Ou, vous pouvez créer une interface qui a les membres que vous voulez, demandez à votre classe dérivée de mettre en œuvre cette interface et programme par rapport à l'interface.

Créé 04/08/2008 à 20:19
source utilisateur

voix
3

Pour masquer complètement et marquer de ne pas utiliser, y compris IntelliSense que je crois que la plupart des lecteurs attendent ...

[Obsolete("Not applicable in this class.")] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
Créé 24/06/2013 à 20:50
source utilisateur

voix
3

Je sais qu'il ya eu plusieurs réponses à cela, et il est assez vieux maintenant, mais la méthode la plus simple est de les déclarer comme new private.

Prenons un exemple, je travaille actuellement sur, où j'ai une API qui rend toutes les méthodes disponibles dans une DLL 3ème partie. Je dois prendre leurs méthodes, mais je veux utiliser une propriété .Net, au lieu d'une méthode « getThisValue » et « setThisValue ». Donc, je construis une deuxième classe, hériter de la première, faire une propriété qui utilise les méthodes get et set, puis remplacer le get original et méthodes définies comme privées. Ils sont toujours disponibles à tous ceux qui veulent construire quelque chose de différent sur eux, mais s'ils veulent juste utiliser le moteur que je construis, ils seront en mesure d'utiliser les propriétés au lieu des méthodes.

En utilisant la méthode double classe se débarrasse de toutes les restrictions à l'impossibilité d'utiliser la newdéclaration pour cacher les membres. Vous ne pouvez pas utiliser overridesi les membres sont marqués comme virtuel.

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; }
}

Maintenant valueEnum est disponible pour les deux classes, mais seulement la propriété est visible dans la classe APIUsageClass. La classe APIClass est toujours disponible pour les personnes qui souhaitent étendre l'API d'origine ou l'utiliser d'une manière différente, et le APIUsageClass est disponible pour ceux qui veulent quelque chose de plus simple.

En fin de compte, ce que je vais faire est de faire le APIClass interne, et seulement exposer ma classe héritée.

Créé 08/12/2010 à 21:54
source utilisateur

voix
1

Je l'ai testé toutes les solutions proposées et ils ne cachent pas vraiment de nouveaux membres.

Mais celui-ci ne:

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

Mais dans le code-behide il est toujours accessible, il faut donc ajouter ainsi obsolète Attribute

[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{ 
    get { return _myHiddenProperty; }
}
Créé 23/05/2012 à 11:19
source utilisateur

voix
0

Vous pouvez utiliser une interface

    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();
        }
    }
Créé 13/11/2017 à 00:24
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more