Domanda

Esiste un modo per accedere al campo di supporto di una proprietà per effettuare la convalida, il rilevamento delle modifiche, ecc.?

È possibile qualcosa di simile al seguente? In caso contrario, ci sono piani per averlo in .NET 4 / C # 4?

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

Il problema principale che ho è che l'uso delle proprietà automatiche non consente la stessa flessibilità di convalida ecc. di una proprietà con un campo di supporto esplicito. Tuttavia, in alcune situazioni un campo di supporto esplicito presenta lo svantaggio di consentire alla classe in cui è contenuto di accedere al campo di supporto quando dovrebbe accedere e riutilizzare la convalida, il rilevamento delle modifiche, ecc. Della proprietà, proprio come qualsiasi altra classe che potrebbe accedere la proprietà esternamente.

Nell'esempio sopra riportato l'accesso al campo di supporto verrebbe limitato alla proprietà, evitando così l'elusione della convalida della proprietà, il rilevamento delle modifiche, ecc.

Modifica: ho cambiato < Backing Field & Gt; a < Parola chiave & Gt ;. Vorrei proporre una nuova parola chiave simile al valore. campo farebbe bene, anche se sono sicuro che sia utilizzato in molti codici esistenti.

È stato utile?

Soluzione

Dopo aver letto i tuoi commenti nella risposta di Mehrdad, penso di capire un po 'meglio il tuo problema.

Sembra che tu sia preoccupato della capacità dello sviluppatore di accedere allo stato privato nella classe che sta scrivendo, ignorando la tua logica di convalida, ecc. Ciò suggerisce che lo stato non dovrebbe essere contenuto nella classe.

Suggerirei la seguente strategia. Scrivi una classe generica che rappresenta un ValidatedValue. Questa classe contiene solo il valore di supporto e consente l'accesso / mutazione solo tramite i metodi get e set. Un delegato viene passato a ValidatedValue per rappresentare la logica di convalida:

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

È possibile, ovviamente, aggiungere più delegati, se necessario (ad esempio, per supportare la notifica di modifica pre / post).

La tua classe ora userebbe ValidatedValue al posto di un archivio di supporto per la tua proprietà.

L'esempio seguente mostra una classe, MyClass, con un numero intero convalidato per essere inferiore a 100. Notare che la logica per generare un'eccezione è in MyClass, non ValidatedValue. Ciò consente di eseguire regole di convalida complesse che dipendono da altri stati contenuti in MyClass. La notazione lambda è stata utilizzata per costruire il delegato di convalida, invece si sarebbe potuto associare a una funzione membro.

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

Spero che sia d'aiuto - un po 'fuori dall'argomento originale, ma penso che sia più in linea con le tue attuali preoccupazioni. Ciò che abbiamo fatto è stato allontanare la logica di convalida dalla proprietà e inserirla nei dati, che è esattamente dove lo si desiderava.

Altri suggerimenti

No non c'è. Se desideri accedere al campo di supporto, non utilizzare le proprietà automatiche e creane uno tuo.

Concordo sul fatto che sarebbe bello avere un campo accessibile solo dalla proprietà e non dal resto della classe. Lo userei sempre.

Come MSDN afferma:

  

" In C # 3.0 e versioni successive, implementato automaticamente   le proprietà fanno una dichiarazione di proprietà   più conciso quando nessuna logica aggiuntiva   è richiesto negli accessi alla proprietà.   Consentono inoltre di creare il codice client   oggetti Quando si dichiara una proprietà come   mostrato nel seguente esempio, il   il compilatore crea un privato, anonimo   il campo di supporto è accessibile solo   attraverso la proprietà ottenere e impostare   di accesso quot. &;

Dato che hai una logica aggiuntiva nei tuoi accessor, l'uso delle proprietà implementate automaticamente non è appropriato nel tuo scenario.

Sebbene il campo di supporto esista, gli viene dato un nome alterato per impedirti di riferirti facilmente - l'idea è che non fai mai riferimento direttamente al campo . Per motivi di interesse, puoi utilizzare Reflector per disassemblare il tuo codice e scoprire il nome del campo, ma ti consiglio di non utilizzare il campo direttamente in quanto questo nome potrebbe effettivamente essere volatile, quindi il tuo codice potrebbe rompersi in qualsiasi momento.

No, ma puoi in una sottoclasse:

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

Se lo farai, perché stai usando le proprietà automatiche ?!

Una semplice proprietà ha fatto ritorno in 1.0. Non credo che abbia senso aggiungere complessità al linguaggio per ogni caso speciale. O hai bisogno della proprietà per fare un semplice store / recuperare il modello o hai bisogno di più. In quest'ultimo caso, farà una proprietà normale.

Non puoi farlo, temo. Questo è uno dei motivi per cui ho iniziato a scrivere MoXAML Power Toys , per fornire la possibilità di converti le proprietà automatiche in Proprietà di notifica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top