2009-05-11 15 views
6

Se ho una variabile privata su cui desidero avere una convalida interna, e voglio mantenere quella convalida in un posto, la metto dietro un getter/setter e solo accedervi con quel getter/setter. Questo è utile quando si tratta di proprietà pubbliche, perché l'altro codice non può accedere alla variabile privata, ma quando ho a che fare con oggetti all'interno della classe stessa, c'è un modo per far rispettare il getter/setter?forzare ottenere/impostare l'accesso di variabili private per proprietà private

private int _eyeOrientation; 

    private int eyeOrientation 
    { 
    get 
    { 
     return _eyeOrientation; 
    } 
    set 
    { 
     if (value < 0) 
     { 
      _eyeOrientation = 0; 
     } 
     else 
     { 
      _eyeOrientation = value % 360; 
     } 
    } 
    } 

Il problema qui è che le altre funzioni della classe possono accidentalmente modificare

_eyeOrientation = -1;

che getterebbe il programma in un tizzy. C'è un modo per ottenere che per generare un errore del compilatore?

+7

E 'un giorno triste quando i programmatori non possono più fidarsi di altre funzioni all'interno della stessa classe:) – codeulike

risposta

10

Sembra che tu abbia bisogno di un tipo di angolo.

// Non mutable Angle class with a normalized, integer angle-value 
public struct Angle 
{ 
    public Angle(int value) 
    { 
    Value = value; 
    } 

    private angle; 
    public Value 
    { 
    get { return angle; } 
    private set { angle = Normalize(value); } 
    } 

    public static int Normalize(int value) 
    { 
    if (value < 0) return 360 - (value % 360); 
    return value % 360; 
    } 
} 

public class SomeClass 
{ 
    public Angle EyeOrientation { get; set; } 
} 

Se si dispone di un certo tipo di valore, come gli angoli, denaro, peso o qualsiasi altra cosa, è sempre una buona prassi per renderlo un proprio tipo, anche se il valore stesso viene memorizzato in un int, decimale ecc. Questo tipo rende le tue interfacce più chiare e sicure. Non è lo stesso se ci si aspetta un angolo o un valore intero come argomento di un metodo.

4

È possibile definirlo in una classe annidata.

public class NeedsEye 
{ 

    Eye _eye = new Eye(); 

    public NeedsEye() 
    { 
     // now, here, any access to the property must be made through the 
     // _eye variable. The Eye class has access to any of the properties 
     // and members of the NeedsEye class, but the NeedsEye class has not 
     // any access to members of the Eye class. 
    } 

    private class Eye 
    { 
     private int _orientation; 

     public int Orientation 
     { 
      get { return _orientation; } 

      if (value < 0) 
      { 
       _eyeOrientation = 0; 
      } 
      else 
      { 
       _eyeOrientation = value % 360; 
      }  
     } 
    } 
} 
1

Basta inserire il proprio attributo privato e getter/setter pubblici in una classe privata.

Quindi solo il getter e il setter possono accedere all'attributo privato.

È eccessivo, ma funzionerebbe. :)

9

In generale, non dovresti preoccuparti di questo. I membri della classe possono ancora utilizzare le proprietà, se non vuoi mettere il controllo nella classe stessa.

Se la tua classe sta diventando così grande da non fidarti più dei metodi all'interno della classe, penserei che è ora di iniziare il refactoring e suddividerlo in classi più piccole che sono più facilmente gestibili.

+0

Sto lavorando su un progetto personale in cui sto cercando di essere più possibile rigorose circa con accesso. Solo per vedere se è possibile avere tutti i tuoi oggetti accessibili SOLO dagli oggetti che ne hanno bisogno. Non hai bisogno di questi se rispetti le buone pratiche di codifica, ma ero curioso di sapere se fosse possibile. – DevinB

1

A seconda delle vostre strumenti si potrebbe guardare in esecuzione di una convenzione di codifica non consente l'accesso diretto a un membro privato di fuori di un get/set

Potrebbe essere un po 'più di lavoro, ma non sarà necessario creare una serie di involucro classi.

3

È possibile contrassegnare il campo come obsoleto in modo che il compilatore generi un avviso se si tenta di accedervi e quindi suppress that warning per il getter/setter della proprietà.

I codici di allarme che si avrebbe bisogno di sopprimere sono CS0612 for the plain Obsolete attribute e CS0618 if the attribute has a custom message.

In generale, lo considero un po 'un trucco e cerco di evitarlo se possibile. Una soluzione migliore sarebbe quella di commentare il codice in modo appropriato e formare i tuoi colleghi sviluppatori in modo che facciano la cosa giusta.

[Obsolete("Please use the EyeOrientation property instead.")] 
private int _eyeOrientation; 

public int EyeOrientation 
{ 
    #pragma warning disable 612, 618 
    get 
    { 
     return _eyeOrientation; 
    } 
    set 
    { 
     _eyeOrientation = (value > 0) ? value % 360 : 0; 
    } 
    #pragma warning restore 612, 618 
} 
+1

(+1) Questa è una soluzione ingegnosamente rotonda – DevinB

+0

È una buona idea, ma non la imposterei su 0, perché un angolo negativo potrebbe essere normalizzato in positivo, ad es. -10 ° == 350 °. –

+0

@Stefan, sono d'accordo. Stavo solo duplicando la funzionalità del codice di esempio nella domanda. – LukeH