45 votes

Masquage des membres hérités

Je cherche un moyen de masquer efficacement les membres hérités. J'ai une bibliothèque de classes qui héritent de classes de base communes. Certaines des classes descendantes les plus récentes héritent de propriétés de dépendance qui sont devenues vestigiales et qui peuvent être un peu déroutantes lors de l'utilisation de la fonction IntelliSense ou en utilisant les classes dans un concepteur visuel.

Ces classes sont toutes des contrôles qui sont écrits pour être compilés pour WPF ou Silverlight 2.0. Je connais ICustomTypeDescriptor et ICustomPropertyProvider mais je suis presque certain qu'ils ne peuvent pas être utilisés dans Silverlight.

Il ne s'agit pas tant d'un problème fonctionnel que d'un problème de convivialité. Que dois-je faire ?

Mise à jour

Certaines des propriétés que j'aimerais vraiment masquer proviennent d'ancêtres qui ne sont pas les miens et, en raison d'un outil spécifique pour lequel je conçois, je ne peux pas masquer les membres avec l'option new opérateur. (Je sais, c'est ridicule)

37voto

caryden Points 4195

Remplacez-les comme Michael le suggère au-dessus de et pour empêcher les gens d'utiliser les méthodes surchargées (sp ?), marquez-les comme obsolètes :

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

Si le second paramètre est défini sur true, une erreur de compilation sera générée si quelqu'un essaie d'appeler cette méthode et que la chaîne dans le premier paramètre est le message. Si parm2 est faux, seul un avertissement du compilateur sera généré.

0 votes

Ne pouvez-vous pas le sceller, également, avec le même effet ?

0 votes

@JamesM no obselete with true prevents member accès l'élément de prévention étanche héritage . Ainsi, une classe scellée ne peut pas être dérivée, et une méthode scellée permet aux autres membres de la classe d'être surchargés mais empêche ce membre d'être surchargé. La méthode scellée n'empêche pas d'appeler cette classe ou ce membre, tandis que la méthode obselete avec true génère une erreur de compilation si vous essayez de l'appeler.

0 votes

@RobertPetz lorsque vous utilisez obsolète, cela donne un avertissement, pas une erreur. Grande différence.

20voto

Michael Stum Points 72046

Bien qu'à ma connaissance, vous ne puissiez pas empêcher l'utilisation de ces membres hérités, vous devriez pouvoir les masquer d'IntelliSense en utilisant la fonction EditorBrowsableAttribute :

Using System.ComponentModel;

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

Editar: Je viens de voir cela dans les commentaires de la documentation, ce qui la rend plutôt inutile pour cet objectif :

Il existe une note importante qui indique que cet attribut "ne supprime pas les membres d'une classe de la même assemblée". C'est vrai mais pas complet. En fait, l'attribut ne supprime pas les membres d'une classe dans la même solution.

14voto

Mike Stone Points 21293

Une chose potentielle que vous pouvez faire est de contenir l'objet plutôt que de l'étendre à partir de l'autre classe. Cela vous donnera la plus grande flexibilité en termes d'exposition de ce que vous voulez exposer, mais si vous avez absolument besoin que l'objet soit de ce type, ce n'est pas la solution idéale (vous pourriez toutefois exposer l'objet à partir 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;
        }
    }
}

8voto

Karl Seguin Points 10566

Je pense que la meilleure façon de faire est de considérer la composition plutôt que l'héritage.

Ou bien, vous pouvez créer une interface qui possède les membres que vous voulez, faire en sorte que votre classe dérivée implémente cette interface, et programmer contre l'interface.

4voto

Nathan Wheeler Points 4068

Je sais qu'il y a eu plusieurs réponses à cette question, et qu'elle est assez ancienne maintenant, mais la méthode la plus simple est de les déclarer en tant que new private .

Prenons un exemple sur lequel je travaille actuellement, où j'ai une API qui rend disponible chaque méthode d'une DLL tierce. Je dois prendre leurs méthodes, mais je veux utiliser une propriété .Net, au lieu d'une méthode "getThisValue" et "setThisValue". Je crée donc une deuxième classe, hérite de la première, crée une propriété qui utilise les méthodes get et set, puis surcharge les méthodes get et set originales en tant que privées. Ils sont toujours disponibles pour quiconque veut construire quelque chose de différent, mais s'ils veulent juste utiliser le moteur que je construis, ils pourront utiliser les propriétés au lieu des méthodes.

L'utilisation de la méthode de la double classe permet de s'affranchir de toutes les restrictions liées à l'impossibilité d'utiliser la méthode de la double classe. new pour cacher les membres. Vous ne pouvez tout simplement pas utiliser override si les membres sont marqués comme virtuels.

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 seule la propriété est visible dans la classe APIUsageClass. La classe APIClass est toujours disponible pour les personnes qui veulent étendre l'API originale ou l'utiliser d'une manière différente, et la classe APIUsageClass est disponible pour ceux qui veulent quelque chose de plus simple.

En fin de compte, ce que je vais faire, c'est rendre l'APIClass interne, et n'exposer que ma classe héritée.

0 votes

Comment l'utiliser pour les propriétés de dépendance ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X