web-dev-qa-db-fra.com

Comment ajouter une propriété à un objet que vous ne pouvez pas modifier?

Disons que j'utilise une bibliothèque et je voudrais ajouter une propriété qui n'existe pas à une classe existante. Dans ce cas, je voudrais ajouter la couleur comme propriété de Fruit.

namespace Library
{
    public class Fruit : System.IDisposable
    {
        public string Name { get; set; }

        public void Dispose() { }
    }
}

Existe-t-il un moyen de le faire en C #?


Exemple qui ne fonctionnera pas

Ma première pensée a été les classes partielles, mais cela nécessiterait que les deux classes contiennent le mot partiel. Ce n'est donc pas faisable.

namespace Library
{
    public partial class Fruit
    {
        public Color Color { get; set; }
    }
}

Cela semble horrible

Je pourrais hériter de Fruit et créer une classe MyFruit. Cela me semble maladroit. Je préfère de loin appeler Person.Fruits.FirstOrDefault (). Color que d'avoir à créer un objet MyPerson qui hérite de Person, puis appeler MyPerson.MyFruits.FirstOrDefault (). Color.

namespace Library
{
    public class MyFruit : Fruit
    {
        public Color Color { get; set; }
    }
}

namespace Library
{
    public class MyPerson : Person
    {
        public MyFruit MyFruit { get; set; }
    }
}
7
MiniRagnarok

La meilleure réponse est que vous ne devriez pas. Mais si cela ne vous dérange pas une surcharge de performances, vous pouvez faire quelque chose de similaire avec ConditionalWeakTable<,>:

public static class ExtraFruitProperties
{
    private static readonly ConditionalWeakTable<Fruit, Color> _colors = new ConditionalWeakTable<Fruit, Color>();

    public static void SetColor(this Fruit @this, Color color) 
    {
         _colors.Remove(@this);
         _colors.Add(@this, color);
    }

    public static Color GetColor(this Fruit @this) 
    {
         Color color;
         if(_colors.TryGetValue(@this, out color)) return color;
         return default(Color);
    }
}
11
afeygin

Vous ne le faites pas.

Le plus proche que vous pouvez obtenir est Java via les méthodes d'extension, bien que si vous avez réellement besoin de stocker la couleur (par opposition à la mapper dans la fonction), il peut être difficile de le faire correctement car la classe d'extension contiendrait des références à la classe réelle si vous le faites de manière naïve.

L'alternative consiste à utiliser l'héritage ou la composition standard pour étendre la classe, que vous avez déjà mentionnée.

1
Telastyn

Utilisez une table de hachage distincte pour ajouter des propriétés aux objets que vous ne contrôlez pas, et utilisez vos propres fonctions d'accès pour encapsuler le comportement que vous souhaitez voir être uniforme par rapport à vos propriétés ajoutées.

Si le garbage collection est susceptible d'être un problème (vos propriétés supplémentaires implémentées de cette façon empêcheront l'objet d'être garbage collection) c'est peut-être le seulement bon usage des tables de hachage d'égalisation faibles.

1
ddyer

Je ne vois pas ce qui est si "horrible" dans votre dernière solution. On vous donne une définition d'un fruit, mais vous voulez qu'il soit plus descriptif. Vous définissez donc une extension de la définition d'origine avec votre ajout de couleur.

Vraiment, pourquoi préférez-vous:

    Person.Fruits.FirstOrDefault().Color 

plus de:

    MyPerson.MyFruits.FirstOrDefault().Color

La seule différence est le préfixe "My" qui est purement cosmétique. Vous pouvez également avoir un nom plus descriptif comme ColoredFruit.

0
Gabe Noblesmith