Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
| Свойство | Значение |
|---|---|
| Идентификатор правила | CA2227 |
| Заголовок | Свойства коллекций должны быть только для чтения |
| Категория | Использование |
| Исправление является критическим или не критическим | Срочное |
| Включен по умолчанию в .NET 10 | Нет |
| Применимые языки | C# и Visual Basic |
Причина
Видимое извне свойство с поддержкой записи имеет тип, реализующий System.Collections.ICollection. Это правило не применяется к массивам, индексаторам (свойствам с именем "Item"), неизменяемым коллекциям, коллекциям только для чтения и наборам разрешений.
Описание правила
Свойство коллекции с возможностью записи позволяет пользователям заменить коллекцию совершенно другой. Свойство только для чтения или только для инициализации не допускает замену коллекции, но по-прежнему позволяет задавать отдельные элементы. Если замена коллекции является целью, предпочтительный шаблон проектирования — включить метод для удаления всех элементов из коллекции и метод для её повторного заполнения. Пример этого шаблона см. в методах Clear и AddRange класса System.Collections.ArrayList.
Как двоичная, так и XML-сериализация поддерживают свойства только для чтения, являющиеся коллекциями. Класс System.Xml.Serialization.XmlSerializer имеет определенные требования к типам, реализующим ICollection и System.Collections.IEnumerable, чтобы быть сериализуемыми.
Устранение нарушений
Используйте один из следующих подходов для устранения нарушения этого правила:
Сделайте свойство только для чтения или только для инициализации. Свойство только для чтения или только для инициализации не позволяет заменять коллекцию, но при этом сохраняет возможность установки отдельных элементов. Если дизайн требует замены содержимого коллекции, добавьте методы для очистки и наполнения коллекции. Пример этого шаблона см. в методах ArrayList.Clear и ArrayList.AddRange.
Измените тип свойства на тип коллекции, доступной только для чтения. Если вызывающим абонентам не нужно изменять коллекцию, измените тип свойства на коллекцию только для чтения, например ReadOnlyCollection<T>. Этот подход делает намерение только для чтения явным в сигнатуре типа.
Измените тип свойства на потокобезопасный параллельный тип коллекции, сохраняя свойство только для чтения. Если проектирование требует несколько потоков для одновременного изменения коллекции, предоставьте свойство только для чтения (без сеттера), тип которого является конкурентной коллекцией, например ConcurrentBag<T>. CA2227 активируется свойством коллекции, доступной для записи, а не типом коллекции, поэтому свойство по-прежнему должно быть доступно только для чтения. Выбор параллельной коллекции обращается только к потокобезопасной мутации возвращаемого экземпляра коллекции.
Когда лучше отключить предупреждения
Предупреждение можно отключить, если свойство является частью класса объекта передачи данных (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 = ["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