Question

Existe-t-il un moyen quelconque d'accéder au champ de sauvegarde d'une propriété afin d'effectuer une validation, un suivi des modifications, etc.?

Est-ce que quelque chose comme ce qui suit est possible? Sinon, envisagez-vous de l’avoir dans .NET 4 / C # 4?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

Le principal problème que j'ai est que l'utilisation des propriétés automatiques ne permet pas la même souplesse de validation, etc. qu'une propriété avec un champ de sauvegarde explicite. Cependant, un champ de sauvegarde explicite présente l'inconvénient, dans certaines situations, d'autoriser la classe dans laquelle elle est contenue à accéder au champ de sauvegarde alors qu'elle devrait pouvoir accéder à la validation, au suivi des modifications, etc. de la propriété, et la réutiliser, comme toute autre classe pouvant y accéder. la propriété à l'extérieur.

Dans l'exemple ci-dessus, l'accès au champ de sauvegarde serait limité à la propriété, empêchant ainsi le contournement de la validation de la propriété, le suivi des modifications, etc.

Modifier: j'ai changé < Zone de support & Gt; à < Mot clé & Gt ;. Je proposerais un nouveau mot clé similaire à value. Le champ conviendrait parfaitement, même si je suis sûr qu'il est utilisé dans de nombreux codes existants.

Était-ce utile?

La solution

Après avoir lu vos commentaires dans la réponse de Mehrdad, je pense que je comprends un peu mieux votre problème.

Il semble que vous soyez préoccupé par la possibilité pour le développeur d'accéder à un état privé dans la classe qu'il écrit, en contournant votre logique de validation, etc. Cela suggère que l'état ne devrait pas du tout être contenu dans la classe.

Je suggérerais la stratégie suivante. Ecrivez une classe générique qui représente une ValidatedValue. Cette classe ne contient que la valeur de support et autorise uniquement les accès / mutations via les méthodes get et set. Un délégué est passé à ValidatedValue pour représenter la logique de validation:

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

Vous pouvez, bien sûr, ajouter plus de délégués si nécessaire (par exemple, pour prendre en charge la notification avant / après modification).

Votre classe utiliserait maintenant ValidatedValue à la place d'un magasin de support pour votre propriété.

L'exemple ci-dessous montre une classe, MyClass, avec un entier validé inférieur à 100. Notez que la logique permettant de lever une exception se trouve dans MyClass, pas dans ValidatedValue. Cela vous permet de faire des règles de validation complexes qui dépendent d'autres états contenus dans MyClass. La notation lambda a été utilisée pour construire le délégué de validation - vous auriez plutôt pu être lié à une fonction membre.

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

J'espère que cela vous aidera - un peu en dehors du sujet initial, mais je pense que cela correspond plus à vos préoccupations actuelles. Ce que nous avons fait est de retirer la logique de validation de la propriété et de la mettre sur les données, qui est exactement là où vous le vouliez.

Autres conseils

Non, il n'y en a pas. Si vous souhaitez accéder au champ de sauvegarde, n'utilisez pas les propriétés automatiques et lancez la vôtre.

Je conviens qu'il serait formidable de disposer d'un champ uniquement accessible par la propriété et non par le reste de la classe. Je l’utiliserais tout le temps.

Les états MSDN sont les suivants:

  

& "; En C # 3.0 et ultérieur, implémenté automatiquement   properties fait une déclaration de propriété   plus concis quand aucune logique supplémentaire   est requis dans les accesseurs de la propriété.   Ils permettent également au code client de créer   objets Lorsque vous déclarez une propriété en tant que   montré dans l'exemple suivant, le   le compilateur crée un nom privé, anonyme   le champ de sauvegarde est accessible uniquement   par le get et set de la propriété   accesseurs. & ";

Étant donné que vous disposez d'une logique supplémentaire dans vos accesseurs, l'utilisation de propriétés implémentées automatiquement n'est pas appropriée dans votre scénario.

Bien que le champ de support existe, un nom mutilé lui est attribué pour vous empêcher de le référencer facilement. L’idée est que vous ne faites jamais directement référence au champ . Par souci d’intérêt, vous pouvez utiliser Reflector pour désassembler votre code et découvrir le nom du champ, mais je vous recommande de ne pas utiliser le champ directement, car ce nom peut en effet être volatile, votre code pourrait donc se rompre à tout moment.

Non, mais vous pouvez dans une sous-classe:

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}

Si vous voulez le faire, pourquoi utilisez-vous les propriétés automatiques?!

Une simple propriété l'a fait depuis la version 1.0. Je ne pense pas qu'il soit logique d'ajouter de la complexité à la langue pour chaque cas particulier. Vous avez besoin de la propriété pour faire un modèle simple de magasin / récupération ou vous avez besoin de plus que cela. Dans ce dernier cas, une propriété normale fera l'affaire.

Vous ne pouvez pas faire cela, j'en ai bien peur. C’est l’une des raisons pour lesquelles j’ai commencé à écrire jouets d'alimentation MoXAML , afin de convertir les propriétés automatiques en propriétés Notify.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top