Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
| Свойство | Значение |
|---|---|
| Идентификатор правила | CA1010 |
| Заголовок | Коллекции должны реализовать универсальный интерфейс |
| Категория | Проектирование |
| Исправление является критическим или не критическим | неразрывный |
| Включен по умолчанию в .NET 10 | Нет |
| Применимые языки | C# и Visual Basic |
Причина
Тип реализует интерфейс System.Collections.IEnumerable, но не реализует интерфейс System.Collections.Generic.IEnumerable<T>, а включающая его сборка предназначена для .NET. Это правило игнорирует типы, реализующие System.Collections.IDictionary.
По умолчанию это правило проверяет только видимые извне типы, но это поведение можно настроить. Кроме того, можно настроить дополнительные интерфейсы, чтобы они требовали реализацию универсального интерфейса.
Описание правила
Чтобы расширить возможности использования коллекции, реализуйте один из универсальных интерфейсов коллекции. Затем данную коллекцию можно использовать для заполнения универсальных типов коллекции, таких как следующие:
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
Устранение нарушений
Чтобы устранить нарушение этого правила, реализуйте один из следующих универсальных интерфейсов коллекции:
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
Когда лучше отключить предупреждения
Можно спокойно скрыть предупреждения для этого правила, но использование коллекции будет ограничено.
Отключение предупреждений
Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.
#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010
Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.
[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none
Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.
Настройка кода для анализа
Используйте следующие параметры, чтобы указать части базы кода, к которым будет применяться это правило.
Эти параметры можно настроить только для этого правила, для всех правил, к которым они применяются, или для всех правил в этой категории (конструкторе), к которым они применяются. Дополнительные сведения см. в статье Параметры конфигурации правила качества кода.
Включите конкретные поверхности API
Вы можете настроить компоненты базы кода для выполнения этого правила на основе их специальных возможностей, задав параметр api_surface. Например, чтобы указать, что правило должно выполняться только для непубличной поверхности API, добавьте следующую пару "ключ-значение" в файл .editorconfig в ваш проект:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Заметка
Замените XXXX частью CAXXXX идентификатором применимого правила.
Дополнительные необходимые универсальные интерфейсы
Вы можете настроить список имен интерфейсов (разделенных |) вместе с их необходимыми универсальными полностью квалифицированными интерфейсами (разделенными ->).
Допустимые форматы интерфейса:
- Только имя интерфейса (включает все интерфейсы с этим именем, независимо от типа или пространства имен, в которых они содержатся).
- Полные имена в формате идентификатора документации для символа с необязательным префиксом
T:.
Примеры:
| Значение опции | Итоги |
|---|---|
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 |
Все типы, которые реализуют ISomething, независимо от его пространства имен, также должны реализовывать System.Collections.Generic.IEnumerable<T>. |
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 |
Все типы, которые реализуют System.Collections.IDictionary, также должны реализовывать System.Collections.Generic.IDictionary<TKey,TValue>. |
Пример
В следующем примере показан класс, производный от класса, не являющегося универсальным, CollectionBase, и нарушающий это правило.
public class Book
{
public Book()
{
}
}
public class BookCollection : CollectionBase
{
public BookCollection()
{
}
public void Add(Book value)
{
InnerList.Add(value);
}
public void Remove(Book value)
{
InnerList.Remove(value);
}
public void Insert(int index, Book value)
{
InnerList.Insert(index, value);
}
public Book? this[int index]
{
get { return (Book?)InnerList[index]; }
set { InnerList[index] = value; }
}
public bool Contains(Book value)
{
return InnerList.Contains(value);
}
public int IndexOf(Book value)
{
return InnerList.IndexOf(value);
}
public void CopyTo(Book[] array, int arrayIndex)
{
InnerList.CopyTo(array, arrayIndex);
}
}
Чтобы устранить нарушение этого правила, выполните одно из следующих действий:
- Реализуйте универсальный интерфейс.
-
Измените базовый класс на тип, который уже реализует универсальные и неуниверсальные интерфейсы, такой как класс
Collection<T>.
Устранение с помощью реализации интерфейса
В примере ниже нарушение устраняется путем реализации следующих универсальных интерфейсов: IEnumerable<T>, ICollection<T> и IList<T>.
public class Book
{
public Book()
{
}
}
public class BookCollection : CollectionBase, IList<Book?>
{
public BookCollection()
{
}
int IList<Book?>.IndexOf(Book? item)
{
return this.List.IndexOf(item);
}
void IList<Book?>.Insert(int location, Book? item)
{
}
Book? IList<Book?>.this[int index]
{
get => (Book?)this.List[index];
set { }
}
void ICollection<Book?>.Add(Book? item)
{
}
bool ICollection<Book?>.Contains(Book? item)
{
return true;
}
void ICollection<Book?>.CopyTo(Book?[] array, int arrayIndex)
{
}
bool ICollection<Book?>.IsReadOnly
{
get { return false; }
}
bool ICollection<Book?>.Remove(Book? item)
{
if (InnerList.Contains(item))
{
InnerList.Remove(item);
return true;
}
return false;
}
IEnumerator<Book> IEnumerable<Book?>.GetEnumerator()
{
return new BookCollectionEnumerator(InnerList.GetEnumerator());
}
private class BookCollectionEnumerator : IEnumerator<Book>
{
private IEnumerator _Enumerator;
public BookCollectionEnumerator(IEnumerator enumerator)
{
_Enumerator = enumerator;
}
public Book Current
{
get { return (Book)_Enumerator.Current; }
}
object IEnumerator.Current
{
get { return _Enumerator.Current; }
}
public bool MoveNext()
{
return _Enumerator.MoveNext();
}
public void Reset()
{
_Enumerator.Reset();
}
public void Dispose()
{
}
}
}
Исправление с помощью изменения базового класса
Следующий пример устраняет нарушение, изменяя базовый класс коллекции с неуниверсального класса CollectionBase на универсальный класс Collection<T> (Collection(Of T) в Visual Basic).
public class Book
{
public Book()
{
}
}
public class BookCollection : Collection<Book>
{
public BookCollection()
{
}
}
Изменение базового класса уже выпущенного класса считается критическим изменением для существующих потребителей.
Связанные правила
- CA1005: не используйте слишком много параметров в универсальных типах
- CA1000: не объявляйте статические элементы в универсальных типах
- CA1002: не следует раскрывать универсальные списки
- CA1003: используйте экземпляры обработчиков событий универсальных типов