Freigeben über


CA2227: Auflistungseigenschaften sollten nur lesbar sein.

Eigenschaft Wert
Regel-ID CA2227
Titel Sammlungseigenschaften sollten schreibgeschützt sein.
Kategorie Verwendung
Fix führt zu Unterbrechungen oder bleibt funktionsfähig Eilmeldung
Standardmäßig in .NET 10 aktiviert Nein
Anwendbare Sprachen C# und Visual Basic

Ursache

Eine extern sichtbare, beschreibbare Eigenschaft ist ein Typ, der System.Collections.ICollection implementiert. Diese Regel ignoriert Arrays, Indexer (Eigenschaften mit dem Namen „Item“), unveränderliche Auflistungen, schreibgeschützte Auflistungen und Berechtigungssätze.

Regelbeschreibung

Mit einer beschreibbaren Auflistungseigenschaft können Benutzer die Auflistung durch eine völlig andere Auflistung ersetzen. Eine schreibgeschützte oder init-only-Eigenschaft verhindert, dass die Auflistung ersetzt wird, aber dennoch einzelne Member festgelegt werden können. Wenn das Ersetzen der Auflistung ein Ziel ist, besteht das bevorzugte Entwurfsmuster darin, eine Methode zum Entfernen aller Elemente aus der Auflistung und eine Methode zum Erneuten Auffüllen der Auflistung einzuschließen. Ein Beispiel für dieses Muster finden Sie unter den Clear- und AddRange-Methoden der System.Collections.ArrayList-Klasse.

Sowohl die binäre als auch die XML-Serialisierung unterstützen schreibgeschützte Eigenschaften, die Auflistungen sind. Die System.Xml.Serialization.XmlSerializer Klasse hat spezifische Anforderungen an Typen, die ICollection und System.Collections.IEnumerable implementieren und serialisierbar sind.

So beheben Sie Verstöße

Verwenden Sie einen der folgenden Ansätze, um einen Verstoß gegen diese Regel zu beheben:

  • Machen Sie die Eigenschaft schreibgeschützt oder nur initialisierbar. Eine schreibgeschützte oder init-only-Eigenschaft verhindert, dass die Auflistung ersetzt wird, während dennoch einzelne Mitglieder geändert werden können. Wenn für das Design das Ersetzen des Inhalts der Auflistung erforderlich ist, fügen Sie Methoden hinzu, um die Auflistung zu löschen und erneut zu füllen. Ein Beispiel für dieses Muster finden Sie unter den ArrayList.Clear Und ArrayList.AddRange Methoden.

  • Ändern Sie den Eigenschaftentyp in einen schreibgeschützten Sammlungstyp. Wenn Aufrufer die Auflistung nicht ändern müssen, ändern Sie den Eigenschaftstyp in eine schreibgeschützte Auflistung, zum Beispiel ReadOnlyCollection<T>. Mit diesem Ansatz wird der schreibgeschützte Zweck in der Typsignatur explizit gemacht.

  • Ändern Sie den Typ der Eigenschaft in einen threadsicheren, konkurrierenden Sammlungstyp, während die Eigenschaft schreibgeschützt bleibt. Wenn das Design erfordert, dass mehrere Threads die Auflistung gleichzeitig ändern, machen Sie eine schreibgeschützte Eigenschaft (kein Setter) verfügbar, deren Typ eine Concurrent Collection, z. B. ConcurrentBag<T>, ist. CA2227 wird durch eine schreibbare Eigenschaft einer Auflistung ausgelöst, nicht durch den Typ der Sammlung, sodass die Eigenschaft weiterhin nur lesbar sein muss. Die Auswahl der Concurrent Collections betrifft nur threadsichere Änderungen der zurückgegebenen Sammlungsinstanz.

Wann sollten Warnungen unterdrückt werden?

Sie können die Warnung unterdrücken, wenn die Eigenschaft Teil einer Datenübertragungsobjeks (DTO)-Klasse ist.

Andernfalls unterdrücken Sie keine Warnungen aus dieser Regel.

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 CA2227
// The code that's violating the rule is on this line.
#pragma warning restore CA2227

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

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

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

Beispiel

Das folgende Beispiel zeigt einen Typ mit einer schreibbaren Sammlungseigenschaft und wie Sie die Sammlung direkt ersetzen können. Außerdem wird die bevorzugte Methode zum Ersetzen einer schreibgeschützten Auflistungseigenschaft mithilfe von den Clear und AddRange Methoden gezeigt.

public class WritableCollection
{
    public ArrayList SomeStrings
    {
        get;

        // This set accessor violates rule CA2227.
        // To fix the code, remove this set accessor or change it to init.
        set;
    }

    public WritableCollection()
    {
        SomeStrings = new ArrayList(new string[] { "one", "two", "three" });
    }
}

class ReplaceWritableCollection
{
    static void Main2227()
    {
        ArrayList newCollection = ["a", "new", "collection"];

        WritableCollection collection = new()
        {
            // This line of code demonstrates how the entire collection
            // can be replaced by a property that's not read only.
            SomeStrings = newCollection
        };

        // If the intent is to replace an entire collection,
        // implement and/or use the Clear() and AddRange() methods instead.
        collection.SomeStrings.Clear();
        collection.SomeStrings.AddRange(newCollection);
    }
}
Public Class WritableCollection

    ' This property violates rule CA2227.
    ' To fix the code, add the ReadOnly modifier to the property:
    ' ReadOnly Property SomeStrings As ArrayList
    Property SomeStrings As ArrayList

    Sub New()
        SomeStrings = New ArrayList(New String() {"one", "two", "three"})
    End Sub

End Class

Class ViolatingVersusPreferred

    Shared Sub Main2227()
        Dim newCollection As New ArrayList(New String() {"a", "new", "collection"})

        Dim collection As New WritableCollection()

        ' This line of code demonstrates how the entire collection
        ' can be replaced by a property that's not read only.
        collection.SomeStrings = newCollection

        ' If the intent is to replace an entire collection,
        ' implement and/or use the Clear() and AddRange() methods instead.
        collection.SomeStrings.Clear()
        collection.SomeStrings.AddRange(newCollection)
    End Sub

End Class

Siehe auch