CA2227: Propriedades de coleção devem ser somente leitura
Property | Valor |
---|---|
ID da regra | CA2227 |
Título | Propriedades de coleção devem ser somente leitura |
Categoria | Usage |
Correção interruptiva ou sem interrupção | Quebra |
Habilitado por padrão no .NET 8 | Não |
Causa
Uma propriedade externamente visível e gravável é de um tipo que implementa System.Collections.ICollection. Essa regra ignora matrizes, indexadores (propriedades com o nome 'Item'), coleções imutáveis, coleções somente leitura e conjuntos de permissões.
Descrição da regra
Uma propriedade de coleção gravável permite que um usuário substitua a coleção por uma coleção completamente diferente. Uma propriedade init-only ou somente leitura impede que a coleção seja substituída, mas ainda permite que os membros individuais sejam definidos. Se o objetivo for substituir a coleção, o padrão de design preferencial será incluir um método para remover todos os elementos da coleção e um método para preencher novamente a coleção. Consulte os método Clear e AddRange da classe System.Collections.ArrayList para obter um exemplo desse padrão.
Tanto a serialização binária quanto o XML dão suporte a propriedades somente leitura que são coleções. A classe System.Xml.Serialization.XmlSerializer possui requisitos específicos para tipos que implementam ICollection e System.Collections.IEnumerable para serem serializáveis.
Como corrigir violações
Para corrigir uma violação dessa regra, torne a propriedade somente leitura ou init-only. Se o design exigir, adicione os métodos para limpar e preencher novamente a coleção.
Quando suprimir avisos
É possível suprimir o aviso se a propriedade fizer parte de uma classe DTO (Objeto de Transferência de Dados).
Caso contrário, não suprima os avisos dessa regra.
Suprimir um aviso
Para suprimir apenas uma violação, adicione diretivas de pré-processador ao arquivo de origem a fim de desabilitar e, em seguida, reabilitar a regra.
#pragma warning disable CA2227
// The code that's violating the rule is on this line.
#pragma warning restore CA2227
Para desabilitar a regra em um arquivo, uma pasta ou um projeto, defina a severidade como none
no arquivo de configuração.
[*.{cs,vb}]
dotnet_diagnostic.CA2227.severity = none
Para obter mais informações, confira Como suprimir avisos de análise de código.
Exemplo
O exemplo a seguir mostra um tipo com uma propriedade de coleção gravável e como é possível substituir a coleção diretamente. Além disso, mostra a maneira preferencial de substituir uma propriedade de coleção somente leitura usando os métodos 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 = new ArrayList(new string[] { "a", "new", "collection" });
WritableCollection collection = 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);
}
}
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