CA1024: Utilizzare proprietà dove appropriato

Proprietà valore
ID regola CA1024
Titolo Usare proprietà dove appropriato
Categoria Progettazione
Correzione che causa un'interruzione o un'interruzione Interruzione
Abilitato per impostazione predefinita in .NET 8 No

Causa

Un metodo ha un nome che inizia con Get, non accetta parametri e restituisce un valore che non è una matrice.

Per impostazione predefinita, questa regola esamina solo i metodi visibili esternamente, ma è configurabile.

Descrizione regola

Nella maggior parte dei casi, le proprietà rappresentano i dati e i metodi eseguono azioni. Le proprietà sono accessibili come i campi, che semplificano l'uso. Un metodo è un buon candidato per diventare una proprietà se è presente una di queste condizioni:

  • Il metodo non accetta argomenti e restituisce le informazioni sullo stato di un oggetto.
  • Il metodo accetta un singolo argomento per impostare parte dello stato di un oggetto.

Come correggere le violazioni

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

Quando eliminare gli avvisi

Eliminare un avviso da questa regola se il metodo soddisfa uno dei criteri seguenti. In queste situazioni, un metodo è preferibile a una proprietà .

  • Il metodo non può comportarsi come campo.
  • Il metodo esegue un'operazione dispendiosa in termini di tempo. Il metodo è in modo percecepibile più lento rispetto al tempo necessario 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 archiviati.
  • Il Get metodo ha un effetto collaterale osservabile. Il recupero del valore di un campo non produce effetti collaterali.
  • L'ordine di esecuzione è importante. L'impostazione del valore di un campo non si basa sull'occorrenza di altre operazioni.
  • La chiamata al metodo due volte in successione crea risultati diversi.
  • Il metodo è static 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 dal campo.
  • Il metodo restituisce una matrice.

Eliminare un avviso

Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.

#pragma warning disable CA1024
// The code that's violating the rule is on this line.
#pragma warning restore CA1024

Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none su nel file di configurazione.

[*.{cs,vb}]
dotnet_diagnostic.CA1024.severity = none

Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.

Configurare il codice da analizzare

Usare l'opzione seguente per configurare le parti della codebase in cui eseguire questa regola.

È possibile configurare questa opzione solo per questa regola, per tutte le regole a cui si applica o per tutte le regole in questa categoria (Progettazione) a cui si applica. Per altre informazioni, vedere Opzioni di configurazione delle regole di qualità del codice.

Includere superfici API specifiche

È possibile configurare le parti della codebase in modo da eseguire questa regola in base all'accessibilità. Ad esempio, per specificare che la regola deve essere eseguita solo sulla superficie dell'API non pubblica, aggiungere la coppia chiave-valore seguente a un file con estensione editorconfig nel progetto:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Esempio

L'esempio seguente contiene diversi metodi che devono essere convertiti in proprietà e diversi non perché non si comportano come campi.

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 violates 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 violates 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 violates 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 violates the rule, but should not be a property.
    // This method performs a conversion.
    public string GetWeekDayString()
    {
        return DateTimeFormatInfo.CurrentInfo.GetDayName(when.DayOfWeek);
    }

    // These methods 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();
    }
}
Public Class Appointment
    Shared nextAppointmentID As Long
    Shared discountScale As Double() = {5.0, 10.0, 33.0}
    Private customerName As String
    Private customerID As Long
    Private [when] As Date

    ' Static constructor.
    Shared Sub New()
        ' Initializes the static variable for Next appointment ID.
    End Sub

    ' This method violates 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 Shared Function GetNextAvailableID() As Long
        nextAppointmentID += 1
        Return nextAppointmentID - 1
    End Function

    ' This method violates the rule, but should not be a property.
    ' This method performs a time-consuming operation. 
    ' This method returns an array.
    Public Function GetCustomerHistory() As Appointment()
        ' Connect to a database to get the customer's appointment history.
        Return LoadHistoryFromDB(customerID)
    End Function

    ' This method violates the rule, but should not be a property.
    ' This method is static but returns a mutable object.
    Public Shared Function GetDiscountScaleForUpdate() As Double()
        Return discountScale
    End Function

    ' This method violates the rule, but should not be a property.
    ' This method performs a conversion.
    Public Function GetWeekDayString() As String
        Return DateTimeFormatInfo.CurrentInfo.GetDayName([when].DayOfWeek)
    End Function

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

    Public Function GetWeekDay() As DayOfWeek
        Return [when].DayOfWeek
    End Function

    Public Sub SetCustomerName(customerName As String)
        Me.customerName = customerName
    End Sub

    Public Function GetCustomerName() As String
        Return customerName
    End Function

    Public Sub SetCustomerID(customerID As Long)
        Me.customerID = customerID
    End Sub

    Public Function GetCustomerID() As Long
        Return customerID
    End Function

    Public Sub SetScheduleTime([when] As Date)
        Me.[when] = [when]
    End Sub

    Public Function GetScheduleTime() As Date
        Return [when]
    End Function

    ' Time-consuming method that is called by GetCustomerHistory.
    Private Function LoadHistoryFromDB(customerID As Long) As Appointment()
        Dim records As ArrayList = New ArrayList()
        Return CType(records.ToArray(), Appointment())
    End Function
End Class

Espansione delle proprietà di controllo nel debugger

Un motivo per cui i programmatori evitano di usare una proprietà è che non vogliono che il debugger esespii automaticamente. Ad esempio, la proprietà potrebbe comportare l'allocazione di un oggetto di grandi dimensioni o la chiamata di un oggetto P/Invoke, ma potrebbe non avere effetti collaterali osservabili.

È possibile impedire al debugger di espandere automaticamente le proprietà applicando System.Diagnostics.DebuggerBrowsableAttribute. Nell'esempio seguente viene illustrato l'applicazione di questo attributo a una proprietà dell'istanza.

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.Diagnostics;

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

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