CA1024: используйте свойства, если это уместно

Свойство Значение
Идентификатор правила CA1024
Заголовок По возможности используйте свойства
Категория Проектирование
Исправление является критическим или не критическим Критическое
Включен по умолчанию в .NET 8 No

Причина

Метод имеет имя, которое начинается с Get, не принимает параметры и возвращает значение, которое не является массивом.

По умолчанию это правило проверяет только видимые извне методы, но это поведение можно настроить.

Описание правила

В большинстве случаев свойства представляют данные, а методы выполняют действия. Доступ к свойствам осуществляется так же, как к полям, что упрощает их использование. Метод может стать свойством, если выполняется любое из следующих условий:

  • Метод не принимает аргументы и возвращает сведения о состоянии объекта.
  • Метод принимает один аргумент для задания части состояния объекта.

Устранение нарушений

Чтобы исправить нарушение этого правила, преобразуйте метод в свойство.

Когда лучше отключить предупреждения

Отключите предупреждения этого правила, если метод удовлетворяет любому из следующих критериев Во всех этих ситуациях предпочтительнее использовать метод, а не свойство.

  • Метод не может вести себя как поле.
  • Метод выполняет длительную операцию. Метод выполняется дольше, чем требуется для задания или получения значения поля.
  • Этот метод выполняет преобразование. При обращении к полю преобразованная версия хранимых данных не возвращается.
  • Использование метода Get связано с заметным побочным эффектом. Получение значения поля не приводит к проявлению побочных эффектов.
  • Порядок выполнения важен. Задание значения поля не зависит от порядка выполнения других операций.
  • Вызов метода два раза приводит к разным результатам.
  • Метод имеет атрибут static, но возвращает объект, который может быть изменен вызывающим объектом. Получение значения поля не позволяет вызывающему объекту изменять данные, хранящиеся в этом поле.
  • Метод возвращает массив.

Отключение предупреждений

Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.

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

Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.

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

Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.

Настройка кода для анализа

Используйте следующий параметр, чтобы выбрать части базы кода для применения этого правила.

Этот параметр можно настроить только для этого правила, для всех правил, к которым он применяется, или для всех правил в этой категории (конструкторе), к которым она применяется. Дополнительные сведения см. в статье Параметры конфигурации правила качества кода.

Включение определенных контактных зон API

Вы можете настроить, для каких частей базы кода следует выполнять это правило в зависимости от их доступности. Например, чтобы указать, что правило должно выполняться только для закрытой контактной зоны API, добавьте следующую пару "ключ-значение" в файл EDITORCONFIG в своем проекте:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Пример

Следующий пример содержит несколько методов, которые следует преобразовать в свойства, и несколько методов, которые преобразовывать не нужно, так как они не ведут себя как поля.

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

Управление развертыванием свойства в отладчике

Иногда программисты не используют свойства, так как они хотят избежать автоматического развертывания в отладчике. Например, свойство может выполнять выделение большого объекта или вызывать P/Invoke и при этом не вызывать заметные побочные эффекты.

Вы можете запретить отладчику автоматическое развертывание свойств, применив System.Diagnostics.DebuggerBrowsableAttribute. В следующем примере показано применение этого атрибута к свойству экземпляра.

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