CA2227: свойства коллекции должны иметь параметр "только для чтения"
Свойство | Значение |
---|---|
Идентификатор правила | CA2227 |
Заголовок | Свойства, возвращающие коллекции, должны быть доступными только для чтения |
Категория | Использование |
Исправление является критическим или не критическим | Критическое |
Включен по умолчанию в .NET 8 | No |
Причина
Видимое извне свойство с поддержкой записи имеет тип, реализующий System.Collections.ICollection. Это правило не применяется к массивам, индексаторам (свойствам с именем "Item"), неизменяемым коллекциям, коллекциям только для чтения и наборам разрешений.
Описание правила
Свойство коллекции, допускающее запись, позволяет пользователю заменять одну коллекцию совершенно другой. Если коллекция имеет свойство "только чтение" или только инициализация, то ее полная замена невозможна, но можно задавать ее отдельные элементы. Если требуется заменить коллекцию, предпочтительным шаблоном разработки является включение метода для удаления всех элементов из коллекции и метода для повторного заполнения коллекции. Пример этого шаблона см. в методах Clear и AddRange класса System.Collections.ArrayList.
Как двоичная, так и XML-сериализация поддерживают свойства только для чтения, являющиеся коллекциями. Сериализуемый класс System.Xml.Serialization.XmlSerializer предъявляет особые требования к типам, которые реализуют ICollection и System.Collections.IEnumerable.
Устранение нарушений
Чтобы устранить нарушение этого правила, измените свойство на "только чтение" или только инициализация. Добавьте методы для очистки и повторного заполнения коллекции, если это требуется для разработки.
Когда лучше отключить предупреждения
Предупреждение можно отключить, если свойство является частью класса объекта передачи данных (DTO).
В противном случае для этого правила отключать вывод предупреждений не следует.
Отключение предупреждений
Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.
#pragma warning disable CA2227
// The code that's violating the rule is on this line.
#pragma warning restore CA2227
Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none
в файле конфигурации.
[*.{cs,vb}]
dotnet_diagnostic.CA2227.severity = none
Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.
Пример
В следующем примере показан тип с доступным для записи свойством коллекции, и демонстрируется прямая замена коллекции. Кроме того, в нем приведен предпочтительный способ замены доступного только для чтения свойства коллекции с помощью методов Clear
и 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