CA1024 : Utiliser les propriétés lorsque cela est approprié

Propriété Value
Identificateur de la règle CA1024
Titre Utiliser les propriétés lorsque cela est approprié
Catégorie Conception
Le correctif est cassant ou non cassant Rupture
Activé par défaut dans .NET 8 Non

Cause

Le nom d’une méthode commence par Get, n’accepte aucun paramètre et retourne une valeur qui n’est pas un tableau.

Par défaut, cette règle examine uniquement les méthodes visibles en externe, mais elle est configurable.

Description de la règle

Dans la plupart des cas, les propriétés représentent des données et les méthodes effectuent des actions. Les propriétés sont accessibles comme des champs, ce qui rend leur utilisation facile. Une méthode est un bon candidat pour devenir une propriété si l’une des conditions suivantes est remplie :

  • La méthode ne prend aucun argument et retourne les informations d’état d’un objet.
  • La méthode accepte un argument unique pour définir une partie de l’état d’un objet.

Comment corriger les violations

Pour corriger une violation de cette règle, remplacez la méthode par une propriété.

Quand supprimer les avertissements

Supprimez un avertissement de cette règle si la méthode correspond à l’un des critères suivants. Dans ces situations, une méthode est préférable à une propriété.

  • La méthode ne peut pas se comporter comme un champ.
  • La méthode effectue une opération chronophage. La méthode est sensiblement plus lente que le temps nécessaire pour définir ou obtenir la valeur d’un champ.
  • La méthode effectue une conversion. L’accès à un champ ne retourne pas une version convertie des données qu’il stocke.
  • La méthode Get a un effet secondaire observable. La récupération de la valeur d’un champ ne génère aucun effet secondaire.
  • L’ordre d’exécution est important. La définition de la valeur d’un champ ne dépend pas de l’occurrence d’autres opérations.
  • L’appel de la méthode deux fois successives crée des résultats différents.
  • La méthode est static mais retourne un objet pouvant être modifié par l’appelant. La récupération de la valeur d’un champ ne permet pas à l’appelant de modifier les données stockées par le champ.
  • La méthode retourne un tableau.

Supprimer un avertissement

Si vous voulez supprimer une seule violation, ajoutez des directives de préprocesseur à votre fichier source pour désactiver et réactiver la règle.

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

Pour désactiver la règle sur un fichier, un dossier ou un projet, définissez sa gravité sur none dans le fichier de configuration.

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

Pour plus d’informations, consultez Comment supprimer les avertissements de l’analyse de code.

Configurer le code à analyser

Utilisez l’option suivante pour configurer les parties de votre codebase sur lesquelles exécuter cette règle.

Vous pouvez configurer cette option pour cette règle uniquement, pour toutes les règles auxquelles elle s’applique ou pour toutes les règles de cette catégorie (Conception) auxquelles elle s’applique. Pour plus d’informations, consultez Options de configuration des règles de qualité du code.

Inclure des surfaces d’API spécifiques

Vous pouvez configurer les parties de votre codebase sur lesquelles exécuter cette règle, en fonction de leur accessibilité. Par exemple, pour spécifier que la règle doit s’exécuter uniquement sur la surface d’API non publique, ajoutez la paire clé-valeur suivante à un fichier .editorconfig dans votre projet :

dotnet_code_quality.CAXXXX.api_surface = private, internal

Exemple

L’exemple suivant contient plusieurs méthodes. Certaines doivent être converties en propriétés et d’autres non, car elles ne se comportent pas comme des champs.

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

Extension de propriété de contrôle dans le débogueur

Les programmeurs évitent parfois d’utiliser une propriété, car ils ne souhaitent pas que le débogueur développe les propriétés automatiquement. Par exemple, la propriété peut impliquer l’allocation d’un objet volumineux ou l’appel de P/Invoke, mais elle peut ne présenter aucun effet secondaire observable.

Vous pouvez empêcher le débogueur de développer automatiquement les propriétés en appliquant System.Diagnostics.DebuggerBrowsableAttribute. L’exemple suivant montre que cet attribut est appliqué à une propriété instance.

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