CA1024: Nach Möglichkeit Eigenschaften verwenden.

Eigenschaft Wert
Regel-ID CA1024
Titel Nach Möglichkeit Eigenschaften verwenden.
Kategorie Design
Fix führt oder führt nicht zur Unterbrechung Breaking
Standardmäßig in .NET 8 aktiviert Nein

Ursache

Eine Methode weist einen Namen auf, der mit Get beginnt. Sie nimmt keine Parameter an und gibt einen Wert zurück, bei dem es sich nicht um ein Array handelt.

Standardmäßig werden mit dieser Regel nur extern sichtbare Methoden überprüft, aber dies ist konfigurierbar.

Regelbeschreibung

In den meisten Fällen stellen Eigenschaften Daten dar, und Methoden führen Aktionen aus. Der Zugriff auf Eigenschaften erfolgt wie bei Feldern, sodass sie einfacher zu verwenden sind. Eine Methode ist ein guter Kandidat für eine Eigenschaft, wenn eine der folgenden Bedingungen erfüllt wird:

  • Die Methode nimmt keine Argumente an und gibt die Zustandsinformationen eines Objekts zurück.
  • Die Methode akzeptiert ein einzelnes Argument, um einen Teil des Zustands eines Objekts festzulegen.

Behandeln von Verstößen

Um einen Verstoß gegen diese Regel zu beheben, ändern Sie die Methode in eine Eigenschaft.

Wann sollten Warnungen unterdrückt werden?

Unterdrücken Sie eine Warnung von dieser Regel, wenn die Methode eines der folgenden Kriterien erfüllt. In diesen Fällen ist eine Methode einer Eigenschaft vorzuziehen.

  • Die Methode kann sich nicht als Feld verhalten.
  • Die Methode führt einen zeitaufwändigen Vorgang aus. Die-Methode ist merklich langsamer als die Zeit, die zum Festlegen oder Abrufen des Werts eines Felds erforderlich ist.
  • Die Methode führt eine Konvertierung aus. Beim Zugriff auf ein Feld wird keine konvertierte Version der darin gespeicherten Daten zurückgegeben.
  • Die Get-Methode führt zu wahrnehmbaren Nebenwirkungen. Beim Abrufen des Werts eines Felds treten keine Nebenwirkungen auf.
  • Die Reihenfolge der Ausführung ist von Bedeutung. Der Wert eines Felds wird nicht basierend auf dem Vorkommen anderer Vorgänge festgelegt.
  • Der zweimalige Aufruf der Methode in Folge führt zu unterschiedlichen Ergebnissen.
  • Die-Methode ist static, gibt jedoch ein Objekt zurück, das vom Aufrufer geändert werden kann. Wenn der Aufrufer den Wert eines Felds abruft, kann er die vom Feld gespeicherten Daten nicht ändern.
  • Die Methode gibt ein Array zurück.

Unterdrücken einer Warnung

Um nur eine einzelne Verletzung zu unterdrücken, fügen Sie der Quelldatei Präprozessoranweisungen hinzu, um die Regel zu deaktivieren und dann wieder zu aktivieren.

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

Um die Regel für eine Datei, einen Ordner oder ein Projekt zu deaktivieren, legen Sie den Schweregrad in der Konfigurationsdatei auf none fest.

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

Weitere Informationen finden Sie unter Vorgehensweise: Unterdrücken von Codeanalyse-Warnungen.

Konfigurieren des zu analysierenden Codes

Mithilfe der folgenden Option können Sie konfigurieren, für welche Teile Ihrer Codebasis diese Regel ausgeführt werden soll.

Sie können diese Optionen nur für diese Regel, für alle zutreffenden Regeln oder für alle zutreffenden Regeln in dieser Kategorie (Entwurf) konfigurieren. Weitere Informationen finden Sie unter Konfigurationsoptionen für die Codequalitätsregel.

Einschließen bestimmter API-Oberflächen

Sie können je nach Zugänglichkeit festlegen, für welche Bestandteile Ihrer Codebasis diese Regel ausgeführt wird. Sie können beispielsweise festlegen, dass die Regel nur für die nicht öffentliche API-Oberfläche ausgeführt werden soll, indem Sie einer EDITORCONFIG-Datei in Ihrem Projekt das folgende Schlüssel-Wert-Paar hinzufügen:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Beispiel

Das folgende Beispiel enthält mehrere Methoden, die in Eigenschaften konvertiert werden sollten, sowie mehrere Methoden, die nicht konvertiert werden sollten, weil sie sich nicht wie Felder verhalten.

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

Steuern der Eigenschaftserweiterung im Debugger

Ein Grund dafür, warum Programmierer die Verwendung einer Eigenschaft vermeiden, liegt darin, dass sie vom Debugger nicht automatisch erweitert werden soll. Die Eigenschaft kann z. B. das Zuordnen eines großen Objekts oder das Aufrufen von P/Invoke beinhalten, aber es treten möglicherweise tatsächlich keine merklichen Nebenwirkungen auf.

Sie können die automatische Erweiterung von Eigenschaften durch den Debugger verhindern, indem Sie System.Diagnostics.DebuggerBrowsableAttribute anwenden. Das folgende Beispiel zeigt, wie dieses Attribut auf eine Instanzeigenschaft angewendet wird.

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