c# - Masquage des membres hérités

Translate

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

Ces classes sont tous des contrôles écrits pour être compilés pour WPF ou Silverlight 2.0. Je connaisICustomTypeDescriptoretICustomPropertyProvider, mais je suis à peu près certain que ceux-ci ne peuvent pas être utilisés dans Silverlight.

Ce n'est pas autant un problème fonctionnel qu'un problème d'utilisabilité. Que devrais-je faire?

Mettre à jour

Certaines des propriétés que j'aimerais vraiment cacher proviennent d'ancêtres qui ne sont pas les miens et, à cause d'un outil spécifique pour lequel je conçois, je ne peux pas cacher un membre avec lenewopérateur. (Je sais, c'est ridicule)

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Remplacez-les comme le suggère Michaelau dessus deet 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 parm est défini sur true, une erreur de compilation sera générée si quelqu'un essaie d'appeler cette méthode et la chaîne du premier parm est le message. Si parm2 est false, seul un avertissement du compilateur sera généré.

La source
Translate

Bien que vous ne puissiez pas empêcher l'utilisation de ces membres hérités à ma connaissance, vous devriez pouvoir les masquer d'IntelliSense à l'aide duEditorBrowsableAttribute:

Using System.ComponentModel;

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

Éditer:Je viens de voir cela dans les commentaires de la documentation, ce qui le rend un peu inutile à cette fin:

Il y a une note bien visible qui indique que cet attribut "ne supprime pas les membres d'une classe dans le même assembly". C'est vrai mais pas complet. En fait, l'attribut ne supprime pas les membres d'une classe dans la même solution.

La source
Translate

Une chose potentielle que vous pouvez faire est de contenir l'objet plutôt que d'étendre à partir 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 que l'objet soit de ce type, ce n'est pas la solution idéale (cependant vous pouvez exposer l'objet à partir d'un getter).

Donc:

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;
        }
    }
}
La source
Translate

Je pense que la meilleure façon la moins hackeuse est de considérer la composition par opposition à l'héritage.

Vous pouvez également créer une interface contenant les membres souhaités, demander à votre classe dérivée d'implémenter cette interface et programmer par rapport à l'interface.

La source
Translate

Je sais qu'il y a eu plusieurs réponses à cela, et c'est assez ancien maintenant, mais la méthode la plus simple pour le faire est simplement de les déclarer commenew private.

Prenons un exemple sur lequel je travaille actuellement, où j'ai une API qui rend disponible toutes les méthodes 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". Donc, je construis une deuxième classe, hérite de la première, crée une propriété qui utilise les méthodes get et set, puis remplace les méthodes get et set d'origine comme privées. Ils sont toujours disponibles pour tous ceux qui souhaitent construire quelque chose de différent sur eux, mais s'ils veulent simplement utiliser le moteur que je construis, ils pourront utiliser des propriétés au lieu de méthodes.

L'utilisation de la méthode de la double classe supprime toute restriction sur l'impossibilité d'utiliser lenewdéclaration pour cacher les membres. Vous ne pouvez tout simplement pas utiliseroverridesi 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 souhaitent étendre l'API d'origine ou l'utiliser d'une manière différente, et l'APIUsageClass est disponible pour ceux qui souhaitent quelque chose de plus simple.

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

La source
Translate

Cacher complètement et marquer pour ne pas utiliser, y compris intellisense, ce que je crois que la plupart des lecteurs attendent ...

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

J'ai testé toutes les solutions proposées et elles ne cachent pas vraiment les nouveaux membres.

Mais celui-ci FAIT:

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

Mais dans code-behide, il est toujours accessible, alors ajoutez également un attribut obsolète

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

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();
        }
    }
La source