CA1010: Kolekcje powinny implementować interfejs generyczny
Właściwości | Wartość |
---|---|
Identyfikator reguły | CA1010 |
Tytuł | Kolekcje powinny implementować interfejs ogólny |
Kategoria | Projekt |
Poprawka powodująca niezgodność lub niezgodność | Niezgodność |
Domyślnie włączone na platformie .NET 9 | Nie. |
Przyczyna
Typ implementuje interfejs, ale nie implementuje System.Collections.IEnumerable interfejsu System.Collections.Generic.IEnumerable<T> i zawiera cele zestawu platformy .NET. Ta reguła ignoruje typy, które implementują System.Collections.IDictionaryprogram .
Domyślnie ta reguła analizuje tylko typy widoczne zewnętrznie, ale można to skonfigurować. Można również skonfigurować dodatkowe interfejsy, aby wymagać zaimplementowania interfejsu ogólnego.
Opis reguły
Aby poszerzyć użyteczność kolekcji, zaimplementuj jeden z interfejsów kolekcji generycznej. Następnie można użyć kolekcji do wypełniania typów kolekcji ogólnych, takich jak:
- System.Collections.Generic.List<T>
- System.Collections.Generic.Queue<T>
- System.Collections.Generic.Stack<T>
Jak naprawić naruszenia
Aby naprawić naruszenie tej reguły, zaimplementuj jeden z następujących interfejsów kolekcji ogólnych:
- System.Collections.Generic.IEnumerable<T>
- System.Collections.Generic.ICollection<T>
- System.Collections.Generic.IList<T>
Kiedy pomijać ostrzeżenia
Można bezpiecznie pominąć ostrzeżenie z tej reguły; jednak użycie kolekcji będzie bardziej ograniczone.
Pomijanie ostrzeżenia
Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.
#pragma warning disable CA1010
// The code that's violating the rule is on this line.
#pragma warning restore CA1010
Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none
w pliku konfiguracji.
[*.{cs,vb}]
dotnet_diagnostic.CA1010.severity = none
Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.
Konfigurowanie kodu do analizowania
Użyj poniższych opcji, aby skonfigurować, które części bazy kodu mają być uruchamiane w tej regule.
Możesz skonfigurować te opcje tylko dla tej reguły, dla wszystkich reguł, do których ma ona zastosowanie, lub dla wszystkich reguł w tej kategorii (Projekt), do których ma ona zastosowanie. Aby uzyskać więcej informacji, zobacz Opcje konfiguracji reguły jakości kodu.
Uwzględnij określone powierzchnie interfejsu API
Możesz skonfigurować, na których częściach bazy kodu ma być uruchamiana ta reguła, na podstawie ich ułatwień dostępu. Aby na przykład określić, że reguła powinna być uruchamiana tylko na powierzchni niepublicznego interfejsu API, dodaj następującą parę klucz-wartość do pliku editorconfig w projekcie:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Dodatkowe wymagane interfejsy ogólne
Listę nazw interfejsów (oddzielonych znakami |
) można skonfigurować przy użyciu wymaganego w pełni kwalifikowanego interfejsu ogólnego (oddzielonego przez ->
).
Dozwolone formaty interfejsu:
- Tylko nazwa interfejsu (zawiera wszystkie interfejsy o nazwie, niezależnie od typu zawierającego lub przestrzeni nazw).
- W pełni kwalifikowane nazwy w formacie identyfikatora dokumentacji symbolu z opcjonalnym
T:
prefiksem.
Przykłady:
Wartość opcji | Podsumowanie |
---|---|
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 |
Oczekuje się również, że wszystkie typy, które implementują ISomething System.Collections.Generic.IEnumerable<T>niezależnie od jego przestrzeni nazw. |
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 |
Oczekuje się również, że wszystkie typy implementujące System.Collections.IDictionary usługę System.Collections.Generic.IDictionary<TKey,TValue>. |
Przykład
W poniższym przykładzie przedstawiono klasę, która pochodzi z klasy niegenerycznej CollectionBase
i narusza tę regułę.
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);
}
}
Aby naprawić naruszenie tej reguły, wykonaj jedną z następujących czynności:
- Zaimplementuj interfejs ogólny.
- Zmień klasę bazową na typ, który już implementuje interfejsy ogólne i nieogólne, takie jak
Collection<T>
klasa.
Poprawka implementacji interfejsu
Poniższy przykład naprawia naruszenie przez zaimplementowanie tych ogólnych interfejsów: IEnumerable<T>, ICollection<T>i 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()
{
}
}
}
Poprawka po zmianie klasy bazowej
Poniższy przykład naprawia naruszenie, zmieniając klasę bazową kolekcji z klasy niegenerycznej CollectionBase
na ogólną Collection<T>
(Collection(Of T)
w Visual Basic).
public class Book
{
public Book()
{
}
}
public class BookCollection : Collection<Book>
{
public BookCollection()
{
}
}
Zmiana klasy bazowej już wydanej klasy jest uważana za zmianę powodującą niezgodność dla istniejących odbiorców.
Powiązane reguły
- CA1005: Unikaj nadużywania parametrów w typach ogólnych
- CA1000: Nie deklaruj składowych statycznych w typach ogólnych
- CA1002: Nie ujawniaj list ogólnych
- CA1003: Użyj wystąpień ogólnej procedury obsługi zdarzeń