Бөлісу құралы:


CA2227: свойства коллекции должны иметь параметр "только для чтения"

Свойство Значение
Идентификатор правила 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

См. также