CA1024: Używaj właściwości wszędzie, gdzie jest to odpowiednie

Właściwości Wartość
Identyfikator reguły CA1024
Stanowisko Używaj właściwości, o ile to możliwe
Kategoria Projekt
Poprawka powodująca niezgodność lub niezgodność Kluczowa
Domyślnie włączone na platformie .NET 8 Nie.

Przyczyna

Metoda ma nazwę rozpoczynającą się od Get, nie przyjmuje parametrów i zwraca wartość, która nie jest tablicą.

Domyślnie ta reguła analizuje tylko metody widoczne zewnętrznie, ale jest to możliwe do skonfigurowania.

Opis reguły

W większości przypadków właściwości reprezentują dane i metody wykonywania akcji. Dostęp do właściwości można uzyskać, takich jak pola, co ułatwia ich używanie. Metoda jest dobrym kandydatem, aby stać się właściwością, jeśli jeden z tych warunków jest obecny:

  • Metoda nie przyjmuje żadnych argumentów i zwraca informacje o stanie obiektu.
  • Metoda akceptuje pojedynczy argument, aby ustawić część stanu obiektu.

Jak naprawić naruszenia

Aby naprawić naruszenie tej reguły, zmień metodę na właściwość.

Kiedy pomijać ostrzeżenia

Pomiń ostrzeżenie z tej reguły, jeśli metoda spełnia jedno z następujących kryteriów. W takich sytuacjach metoda jest preferowana dla właściwości.

  • Metoda nie może zachowywać się jako pole.
  • Metoda wykonuje czasochłonną operację. Metoda jest prawdopodobnie wolniejsza niż czas wymagany do ustawienia lub pobrania wartości pola.
  • Metoda wykonuje konwersję. Uzyskiwanie dostępu do pola nie zwraca przekonwertowanej wersji przechowywanych danych.
  • Metoda Get ma zauważalny efekt uboczny. Pobieranie wartości pola nie powoduje żadnych skutków ubocznych.
  • Kolejność wykonywania jest ważna. Ustawienie wartości pola nie polega na wystąpieniu innych operacji.
  • Wywołanie metody dwa razy z rzędu powoduje utworzenie różnych wyników.
  • Metoda jest static ale zwraca obiekt, który można zmienić przez obiekt wywołujący. Pobieranie wartości pola nie zezwala wywołującym na zmianę danych przechowywanych przez pole.
  • Metoda zwraca tablicę.

Pomijanie ostrzeżenia

Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.

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

Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none w pliku konfiguracji.

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

Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.

Konfigurowanie kodu do analizowania

Użyj następującej opcji, aby skonfigurować, które części bazy kodu mają być uruchamiane w tej regule.

Tę opcję można skonfigurować tylko dla tej reguły, dla wszystkich reguł, do których ma ona zastosowanie, lub dla wszystkich reguł w tej kategorii (Projekt), których dotyczy. Aby uzyskać więcej informacji, zobacz Opcje konfiguracji reguły jakości kodu.

Uwzględnij określone powierzchnie interfejsu API

Możesz skonfigurować, na których częściach bazy kodu ma być uruchamiana ta reguła, na podstawie ich ułatwień dostępu. Aby na przykład określić, że reguła powinna być uruchamiana tylko na powierzchni niepublicznego interfejsu API, dodaj następującą parę klucz-wartość do pliku editorconfig w projekcie:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Przykład

Poniższy przykład zawiera kilka metod, które powinny być konwertowane na właściwości i kilka, które nie powinny zachowywać się jak pola.

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

Rozszerzanie właściwości kontrolki w debugerze

Jednym z powodów, dla których programiści unikają używania właściwości, jest to, że nie chcą, aby debuger automatycznie go rozpalił. Na przykład właściwość może obejmować przydzielanie dużego obiektu lub wywoływanie wywołania P/Invoke, ale może nie mieć żadnych zauważalnych skutków ubocznych.

Aby zapobiec automatycznemu rozszerzaniu właściwości debugera, zastosuj polecenie System.Diagnostics.DebuggerBrowsableAttribute. W poniższym przykładzie pokazano, że ten atrybut jest stosowany do właściwości wystąpienia.

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