Condividi tramite


CA1024: Utilizzare proprietà dove appropriato

TypeName

UsePropertiesWhereAppropriate

CheckId

CA1024

Category

Microsoft.Design

Breaking Change

Breaking

Causa

Un metodo pubblico o protetto presenta un nome che inizia con Get, non accetta parametri e restituisce un valore diverso da una matrice.

Descrizione della regola

Nella maggior parte dei casi, le proprietà rappresentano dati e i metodi eseguono azioni. Alle proprietà si accede come ai campi e sono pertanto più semplici da utilizzare. Un metodo è un buon candidato per divenire una proprietà in presenza di una delle seguenti condizioni:

  • Non accetta argomenti e restituisce le informazioni sullo stato di un oggetto.

  • Accetta un solo argomento per impostare parte dello stato di un oggetto.

Le proprietà devono presentare un comportamento analogo ai campi. Se il metodo non può presentare un comportamento simile, non deve essere modificato in una proprietà. I metodi sono preferibili alle proprietà nelle situazioni riportate di seguito:

  • Il metodo esegue un'operazione che richiede molto tempo. Il metodo è sensibilmente più lento rispetto al tempo richiesto per impostare o ottenere il valore di un campo.

  • Il metodo esegue una conversione. L'accesso a un campo non restituisce una versione convertita dei dati in esso archiviati.

  • Il metodo Get presenta un effetto collaterale osservabile. Il recupero del valore di un campo non produce alcun effetto secondario.

  • L'ordine di esecuzione è importante. L'impostazione del valore di un campo non si basa sull'esecuzione di altre operazioni.

  • Se il metodo viene chiamato due volte consecutive, si otterranno risultati diversi.

  • Il metodo è statico ma restituisce un oggetto che può essere modificato dal chiamante. Il recupero del valore di un campo non consente al chiamante di modificare i dati archiviati nel campo.

  • Il metodo restituisce una matrice.

Come correggere le violazioni

Per correggere una violazione di questa regola, modificare il metodo in una proprietà.

Esclusione di avvisi

Eliminare un avviso da questa regola se il metodo soddisfa almeno uno dei criteri elencati in precedenza.

Controllo dell'espansione di proprietà nel debugger

Uno dei motivi per cui i programmatori tendono ad evitare l'utilizzo di proprietà è che non desiderano che il debugger le espanda automaticamente. Ad esempio, la proprietà potrebbe prevedere l'allocazione di un oggetto di grandi dimensioni o la chiamata a P/Invoke, ma potrebbe non avere effetti collaterali osservabili di alcun genere.

È possibile impedire che debugger espanda le proprietà automaticamente applicando System.Diagnostics.DebuggerBrowsableAttribute. Nell'esempio seguente è mostrato questo attributo applicato a una proprietà di istanza.

Imports System 
Imports System.Diagnostics 

Namespace Microsoft.Samples 

    Public Class TestClass 

        ' [...] 

        <DebuggerBrowsable(DebuggerBrowsableState.Never)> _ 
        Public ReadOnly Property LargeObject() As LargeObject 
            Get 
                ' Allocate large object 
                ' [...] 
            End Get 
        End Property 

    End Class 

End Namespace
using System; 
using System.Diagnostics; 

namespace Microsoft.Samples 
{ 
    public class TestClass 
    { 
        // [...] 

        [DebuggerBrowsable(DebuggerBrowsableState.Never)] 
        public LargeObject LargeObject 
        { 
            get 
            { 
                // Allocate large object 
                // [...] 

        }
    }
}

Esempio

Nell'esempio riportato di seguito sono contenuti diversi metodi che devono essere convertiti in proprietà e altri metodi che non devono essere convertiti perché non presentano comportamenti analoghi a campi.

using System;
using System.Globalization;
using System.Collections;
namespace DesignLibrary
{
   // Illustrates the behavior of rule: 
   //  UsePropertiesWhereAppropriate.

   public class Appointment
   {
      static long nextAppointmentID;
      static double[] discountScale = {5.0, 10.0, 33.0};
      string customerName;
      long customerID;
      DateTime when;

      // Static constructor.
      static Appointment()
      {
         // Initializes the static variable for Next appointment ID.
      }

      // This method will violate the rule, but should not be a property.
      // This method has an observable side effect. 
      // Calling the method twice in succession creates different results.
      public static long GetNextAvailableID()
      {
         nextAppointmentID++;
         return nextAppointmentID - 1;
      }

      // This method will violate the rule, but should not be a property.
      // This method performs a time-consuming operation. 
      // This method returns an array.

      public Appointment[] GetCustomerHistory()
      {
         // Connect to a database to get the customer's appointment history.
         return LoadHistoryFromDB(customerID);
      }

      // This method will violate the rule, but should not be a property.
      // This method is static but returns a mutable object.
      public static double[] GetDiscountScaleForUpdate()
      {
         return discountScale;
      }

      // This method will violate the rule, but should not be a property.
      // This method performs a conversion.
      public string GetWeekDayString()
      {
         return DateTimeFormatInfo.CurrentInfo.GetDayName(when.DayOfWeek);
      }

      // These methods will violate the rule, and should be properties.
      // They each set or return a piece of the current object's state.

      public DayOfWeek GetWeekDay ()
      {
         return when.DayOfWeek;
      }

      public void  SetCustomerName (string customerName)
      {
         this.customerName = customerName;
      }
      public string GetCustomerName ()
      {
         return customerName;
      }

     public void SetCustomerID (long customerID)
      {
         this.customerID = customerID;
      }

      public long GetCustomerID ()
      {
         return customerID;
      }

      public void SetScheduleTime (DateTime when)
      {
         this.when = when;
      }

      public DateTime GetScheduleTime ()
      {
         return when;
      }

      // Time-consuming method that is called by GetCustomerHistory.
      Appointment[] LoadHistoryFromDB(long customerID)
      {
         ArrayList records = new ArrayList();
         // Load from database.
         return (Appointment[])records.ToArray();
      }
   }
}