CA1024: Usar propriedades quando apropriado

Property Valor
ID da regra CA1024
Título Usar propriedades quando apropriado
Categoria Projetar
Correção interruptiva ou sem interrupção Quebra
Habilitado por padrão no .NET 8 Não

Causa

Um método tem um nome que começa com Get, não utiliza parâmetros e retorna um valor que não é uma matriz.

Por padrão, essa regra apenas analisa os métodos visíveis externamente, mas isso é configurável.

Descrição da regra

Na maioria dos casos, as propriedades representam dados, e os métodos executam ações. As propriedades são acessadas como campos, o que as torna mais fáceis de usar. Um método é um bom candidato para se tornar uma propriedade se uma dessas condições estiver presente:

  • O método não usa argumentos e retorna as informações de estado de um objeto.
  • O método aceita um único argumento para definir parte do estado de um objeto.

Como corrigir violações

Para corrigir uma violação dessa regra, altere o método para uma propriedade.

Quando suprimir avisos

Suprime um aviso dessa regra se o método atender a um dos critérios a seguir. Nessas situações, um método é preferível a uma propriedade.

  • O método não pode se comportar como um campo.
  • O método executa uma operação demorada. O método é perceptivelmente mais lento do que o tempo necessário para definir ou obter o valor de um campo.
  • O método executa uma conversão. Acessar um campo não retorna uma versão convertida dos dados que ele armazena.
  • O método Get tem um efeito colateral observável. Recuperar o valor de um campo não produz efeitos colaterais.
  • A ordem de execução é importante. Definir o valor de um campo não depende da ocorrência de outras operações.
  • Chamar o método duas vezes consecutivas cria resultados diferentes.
  • O método é static, mas retorna apenas um objeto que pode ser alterado pelo chamador. Recuperar o valor de um campo não permite que o chamador altere os dados armazenados pelo campo.
  • O método retorna uma matriz.

Suprimir um aviso

Para suprimir apenas uma violação, adicione diretivas de pré-processador ao arquivo de origem a fim de desabilitar e, em seguida, reabilitar a regra.

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

Para desabilitar a regra em um arquivo, uma pasta ou um projeto, defina a severidade como none no arquivo de configuração.

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

Para obter mais informações, confira Como suprimir avisos de análise de código.

Configurar código para analisar

Use a opção a seguir para configurar em quais partes da base de código essa regra deve ser executada.

Você pode configurar essa opção apenas para essa regra, para todas as regras às quais ela se aplica ou para todas as regras nessa categoria (Design) às quais ela se aplica. Para saber mais, confira Opções de configuração de regra de qualidade de código.

Incluir superfícies de API específicas

É possível configurar em quais partes da base de código essa regra deverá ser executada, com base na acessibilidade. Por exemplo, para especificar que a regra deverá ser executada apenas na superfície de API não pública, adicione o seguinte par chave-valor a um arquivo .editorconfig no projeto:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Exemplo

O exemplo a seguir contém vários métodos que devem ser convertidos em propriedades e vários que não devem, porque não se comportam como campos.

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

Controlar a expansão da propriedade no depurador

Um dos motivos pelos quais os programadores evitam usar uma propriedade é porque não querem que o depurador a autoexpanda automaticamente. Por exemplo, a propriedade pode envolver alocar um objeto grande ou chamar um P/Invoke, mas pode não ter efeitos colaterais observáveis.

Para impedir que o depurador autoexpanda as propriedades, aplique System.Diagnostics.DebuggerBrowsableAttribute. O exemplo a seguir mostra esse atributo sendo aplicado a uma propriedade de instância.

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
                // [...]
            }
        }
    }
}