Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
| Vlastnost | Hodnota |
|---|---|
| ID pravidla | CA2227 |
| Název | Vlastnosti kolekce by měly být nastavitelné pouze ke čtení |
| Kategorie | Využití |
| Oprava, která může být destruktivní nebo nedestruktivní | Přerušující |
| Povoleno ve výchozím nastavení v .NET 10 | Ne |
| Příslušné jazyky | C# a Visual Basic |
Příčina
Externě viditelná zapisovatelná vlastnost je typu, který implementuje System.Collections.ICollection. Toto pravidlo ignoruje pole, indexery (vlastnosti s názvem Item), neměnné kolekce, kolekce jen pro čtení a sady oprávnění.
Popis pravidla
Zapisovatelná vlastnost kolekce umožňuje uživatelům nahradit kolekci úplně jinou kolekcí. Vlastnost jen pro čtení nebo pouze pro inicializaci zabraňuje nahrazení kolekce, ale přesto umožňuje nastavit jednotlivé členy. Pokud je nahrazení kolekce cílem, upřednostňovaným vzorem návrhu je zahrnout metodu pro odebrání všech prvků z kolekce a metodu pro opětovné naplnění kolekce. Příklady tohoto vzoru naleznete v metodách Clear a AddRange třídy System.Collections.ArrayList.
Binární serializace i serializace XML podporují vlastnosti jen pro čtení, které jsou kolekce. Třída System.Xml.Serialization.XmlSerializer má specifické požadavky pro typy, které implementují ICollection a System.Collections.IEnumerable mají být serializovatelné.
Jak opravit porušení
K opravě porušení tohoto pravidla použijte jeden z následujících přístupů:
Umožňuje nastavit vlastnost jen pro čtení nebo jen pro inicializaci. Vlastnost jen pro čtení nebo init-only zabraňuje nahrazení kolekce, zatímco stále umožňuje nastavit jednotlivé členy. Pokud návrh vyžaduje nahrazení obsahu kolekce, přidejte metody pro vymazání a opětovné naplnění kolekce. Příklad tohoto modelu najdete v metodách ArrayList.Clear a ArrayList.AddRange.
Změňte typ vlastnosti na typ kolekce jen pro čtení. Pokud volající nemusí kolekci upravovat, změňte typ vlastnosti na kolekci určenou jen pro čtení, například ReadOnlyCollection<T>. Díky tomuto přístupu je záměr pro čtení explicitní v deklaraci typu.
Změňte typ vlastnosti na typ kolekce, která je bezpečná pro souběžný přístup z více vláken, a současně ponechte vlastnost jen pro čtení. Pokud návrh vyžaduje ke souběžné úpravě kolekce více vláken, zpřístupňte vlastnost jen pro čtení (bez setter), jejíž typ je souběžná kolekce, například ConcurrentBag<T>. CA2227 se aktivuje zapisovatelnou vlastností kolekce, nikoli typem kolekce, proto musí být vlastnost stále nastavena jako jen pro čtení. Souběžný výběr kolekce řeší pouze bezpečnou mutaci vrácené instance kolekce.
Kdy potlačit upozornění
Upozornění můžete potlačit, pokud je vlastnost součástí třídy DTO (Data Transfer Object).
Jinak neignorujte upozornění z tohoto pravidla.
Potlačení upozornění
Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.
#pragma warning disable CA2227
// The code that's violating the rule is on this line.
#pragma warning restore CA2227
Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none konfiguračním souboru.
[*.{cs,vb}]
dotnet_diagnostic.CA2227.severity = none
Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.
Příklad
Následující příklad ukazuje typ s vlastností zapisovatelné kolekce a jak můžete kolekci přímo nahradit. Ukazuje také upřednostňovaný způsob nahrazení vlastnosti kolekce jen pro čtení pomocí Clear a AddRange metod.
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