CA1024: Utilizar las propiedades donde corresponda

Propiedad Value
Identificador de la regla CA1024
Título Utilizar las propiedades donde corresponda
Categoría Diseño
La corrección es problemática o no problemática Problemático
Habilitado de forma predeterminada en .NET 8 No

Causa

Un método tiene un nombre que comienza por Get, no adopta ningún parámetro y devuelve un valor que no es una matriz.

De forma predeterminada, esta regla solo examina los métodos visibles externamente, pero es configurable.

Descripción de la regla

En la mayoría de los casos, las propiedades representan datos y los métodos realizan acciones. A las propiedades se accede de la misma forma que a los campos, lo que facilita su uso. Un método es un buen candidato para convertirse en una propiedad si cumple alguna de estas condiciones:

  • El método no adopta ningún argumento y devuelve la información de estado de un objeto.
  • El método acepta un solo argumento para establecer parte del estado de un objeto.

Cómo corregir infracciones

Para corregir una infracción de esta regla, cambie el método a una propiedad.

Cuándo suprimir advertencias

Suprima una advertencia de esta regla si el método cumple alguno de los siguientes criterios. En estas situaciones, se prefiere un método en lugar de una propiedad.

  • El método no puede comportarse como un campo.
  • El método realiza una operación que lleva mucho tiempo. Se percibe que el método consume más tiempo con respecto a lo que se tarda en establecer u obtener el valor de un campo.
  • El método realiza una conversión. El acceso a un campo no devuelve una versión convertida de los datos que almacena.
  • El método Get tiene un efecto secundario observable. La recuperación del valor de un campo no produce efectos secundarios.
  • El orden de ejecución es importante. El establecimiento del valor de un campo no se basa en la aparición de otras operaciones.
  • La llamada al método dos veces sucesivas devuelve resultados diferentes.
  • El método es static, pero devuelve un objeto que el autor de la llamada puede cambiar. La recuperación del valor de un campo no permite al autor de la llamada cambiar los datos almacenados por el campo.
  • El método devuelve una matriz.

Supresión de una advertencia

Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.

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

Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none del archivo de configuración.

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

Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.

Configuración del código para analizar

Use la opción siguiente para configurar en qué partes del código base ejecutar esta regla.

Puede configurar esta opción solo para esta regla, para todas las reglas a las que se aplica o para todas las reglas de esta categoría (Diseño) a las que se aplica. Para más información, vea Opciones de configuración de reglas de calidad de código.

Incluir superficies de API específicas

Puede configurar en qué partes del código base ejecutar esta regla, en función de su accesibilidad. Por ejemplo, para especificar que la regla solo se debe ejecutar en la superficie de API no públicas, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Ejemplo

El ejemplo siguiente contiene varios métodos que se deben convertir en propiedades y otros que no deberían hacerlo porque no se comportan 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

Control de la expansión de propiedades en el depurador

Un motivo por el que los programadores evitan el uso de una propiedad es porque no quieren que el depurador la expanda automáticamente. Por ejemplo, la propiedad puede implicar la asignación de un objeto grande o la llamada a P/Invoke, pero podría no tener realmente efectos secundarios observables.

Con la aplicación de System.Diagnostics.DebuggerBrowsableAttribute, puede evitar que el depurador expanda automáticamente las propiedades. En el ejemplo siguiente se muestra la aplicación de este atributo a la propiedad de una instancia.

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