CA2227: Verzamelingseigenschappen moeten alleen lezen zijn

Eigenschap Waarde
Regel-id CA2227
Titel Verzamelingseigenschappen mogen alleen lezen zijn
Categorie Gebruik
Fix kan brekend of niet-brekend zijn Onderbreking
Standaard ingeschakeld in .NET 10 Nee
Toepasselijke talen C# en Visual Basic

Oorzaak

Een extern zichtbare, beschrijfbare eigenschap is van een type dat implementeert System.Collections.ICollection. Deze regel negeert matrices, indexeerfuncties (eigenschappen met de naam Item), onveranderbare verzamelingen, leesbare verzamelingen en machtigingensets.

Beschrijving van regel

Met een beschrijfbare verzamelingseigenschap kunnen gebruikers de verzameling vervangen door een volledig andere verzameling. Met een alleen-lezen of init-only eigenschap wordt voorkomen dat de verzameling wordt vervangen, maar kunnen individuele leden nog steeds worden ingesteld. Als het vervangen van de verzameling een doel is, is het voorkeursontwerppatroon een methode op te nemen om alle elementen uit de verzameling te verwijderen en een methode om de verzameling opnieuw te vullen. Bekijk de Clear en AddRange methoden van de System.Collections.ArrayList klasse voor een voorbeeld van dit patroon.

Zowel binaire als XML-serialisatie ondersteunen alleen-lezeneigenschappen die verzamelingen zijn. De System.Xml.Serialization.XmlSerializer klasse heeft specifieke vereisten voor typen die ICollection en System.Collections.IEnumerable implementeren om serialiseerbaar te zijn.

Hoe schendingen op te lossen

Gebruik een van de volgende methoden om een schending van deze regel op te lossen:

  • Maak de eigenschap alleen-lezen of alleen-initialiseerbaar. Een eigenschap alleen-lezen of init-only voorkomt dat de verzameling wordt vervangen terwijl het nog steeds mogelijk is om individuele leden in te stellen. Als voor het ontwerp de inhoud van de verzameling moet worden vervangen, voegt u methoden toe om de verzameling te wissen en opnieuw te vullen. Zie de ArrayList.Clear en ArrayList.AddRange methoden voor een voorbeeld van dit patroon.

  • Wijzig het eigenschapstype in een alleen-lezen verzamelingstype. Als de aanroepen de verzameling niet hoeven te wijzigen, verander het eigenschapstype naar een alleen-lezen verzameling, zoals ReadOnlyCollection<T>. Deze benadering maakt de alleen-lezen intentie expliciet in de typesignatuur.

  • Wijzig het eigenschapstype in een thread-veilig gelijktijdig verzamelingstype, terwijl u de eigenschap alleen-lezen houdt. Als voor het ontwerp meerdere threads nodig zijn om de verzameling gelijktijdig te wijzigen, stelt u een alleen-lezeneigenschap (geen setter) beschikbaar waarvan het type een gelijktijdige verzameling is, zoals ConcurrentBag<T>. CA2227 wordt geactiveerd door een beschrijfbare verzamelingseigenschap, niet door het verzamelingstype, dus de eigenschap moet nog steeds alleen-lezen zijn. De keuze voor gelijktijdige verzameling heeft alleen betrekking op de thread-safe mutatie van het geretourneerde verzamelingsexemplaar.

Wanneer waarschuwingen onderdrukken

U kunt de waarschuwing onderdrukken als de eigenschap deel uitmaakt van een DTO-klasse (Data Transfer Object).

Anders moet u de waarschuwingen van deze regel niet onderdrukken.

Een waarschuwing onderdrukken

Als u slechts één schending wilt onderdrukken, voegt u preprocessorrichtlijnen toe aan uw bronbestand om de regel uit te schakelen en vervolgens opnieuw in te schakelen.

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

Als u de regel voor een bestand, map of project wilt uitschakelen, stelt u de ernst none ervan in op het configuratiebestand.

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

Zie voor meer informatie Hoe codeanalysewaarschuwingen te onderdrukken.

Voorbeeld

In het volgende voorbeeld ziet u een type met een beschrijfbare verzamelingseigenschap en hoe u de verzameling rechtstreeks kunt vervangen. Het toont ook de voorkeursmethode om een alleen-lezen collectie-eigenschap te vervangen door de methoden Clear en AddRange.

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

Zie ook