Condividi tramite


CA2227: Le proprietà delle raccolte devono essere in sola lettura

Proprietà valore
ID regola CA2227
Title Le proprietà di raccolte devono essere in sola lettura
Categoria Utilizzo
La correzione causa un'interruzione o meno Interruzione
Abilitato per impostazione predefinita in .NET 10 No
Linguaggi applicabili C# e Visual Basic

Causa

Una proprietà visibile esternamente scrivibile è di un tipo che implementa System.Collections.ICollection. Questa regola ignora matrici, indicizzatori (proprietà con il nome 'Item'), raccolte non modificabili, raccolte readonly e set di autorizzazioni.

Descrizione regola

Una proprietà di raccolta scrivibile consente agli utenti di sostituire la raccolta con una raccolta completamente diversa. Una proprietà di sola lettura o di sola inizializzazione impedisce la sostituzione della raccolta, ma consente comunque di modificare i singoli membri. Se la sostituzione della raccolta è un obiettivo, il modello di progettazione preferito consiste nell'includere un metodo per rimuovere tutti gli elementi dalla raccolta e un metodo per ripopolare la raccolta. Per un esempio di questo modello, vedere i metodi Clear e AddRange della classe System.Collections.ArrayList.

La serializzazione binaria e XML supporta le proprietà di sola lettura che costituiscono raccolte. La System.Xml.Serialization.XmlSerializer classe ha requisiti specifici per i tipi che implementano ICollection e System.Collections.IEnumerable devono essere serializzabili.

Come correggere le violazioni

Usare uno degli approcci seguenti per correggere una violazione di questa regola:

  • Imposta la proprietà come di sola lettura o solo init. Una proprietà di sola lettura o di sola inizializzazione impedisce la sostituzione della raccolta, consentendo comunque l'impostazione dei singoli membri. Se la progettazione richiede la sostituzione del contenuto della raccolta, aggiungere metodi per cancellare e ripopolare la raccolta. Per un esempio di questo modello, vedere i metodi ArrayList.Clear e ArrayList.AddRange.

  • Modificare il tipo di proprietà in un tipo di raccolta di sola lettura. Se i chiamanti non devono modificare la raccolta, cambiare il tipo di proprietà in una raccolta di sola lettura, ad esempio ReadOnlyCollection<T>. Questo approccio rende esplicita la finalità di sola lettura nella firma del tipo.

  • Modificare il tipo di proprietà in un tipo di raccolta simultaneo thread-safe, mantenendo la proprietà di sola lettura. Se la progettazione richiede più thread per modificare la raccolta contemporaneamente, esporre una proprietà di sola lettura (nessun setter) il cui tipo è un insieme simultaneo, ad esempio ConcurrentBag<T>. CA2227 viene attivato da una proprietà di raccolta scrivibile, non dal tipo di raccolta, pertanto la proprietà deve comunque essere di sola lettura. La scelta della raccolta concorrente si concentra solo sulla mutazione thread-safe dell'istanza di raccolta restituita.

Quando eliminare gli avvisi

È possibile eliminare l'avviso se la proprietà fa parte di una classe DTO (Data Transfer Object).

In caso contrario, non eliminare gli avvisi da questa regola.

Eliminare un avviso

Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.

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

Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none su nel file di configurazione.

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

Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.

Esempio

Nell'esempio seguente viene illustrato un tipo con una proprietà di raccolta scrivibile e come sostituire direttamente la raccolta. Mostra anche il modo preferito per sostituire una proprietà di una collezione di sola lettura utilizzando i metodi Clear e 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

Vedi anche